Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be | 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. | 3 // found in the LICENSE file. |
| 4 | 4 |
| 5 #ifndef BASE_MAC_SCOPED_NSOBJECT_H_ | 5 #ifndef BASE_MAC_SCOPED_NSOBJECT_H_ |
| 6 #define BASE_MAC_SCOPED_NSOBJECT_H_ | 6 #define BASE_MAC_SCOPED_NSOBJECT_H_ |
| 7 | 7 |
| 8 #include <type_traits> | 8 #include <type_traits> |
| 9 | 9 |
| 10 // Include NSObject.h directly because Foundation.h pulls in many dependencies. | 10 // Include NSObject.h directly because Foundation.h pulls in many dependencies. |
| 11 // (Approx 100k lines of code versus 1.5k for NSObject.h). scoped_nsobject gets | 11 // (Approx 100k lines of code versus 1.5k for NSObject.h). scoped_nsobject gets |
| 12 // singled out because it is most typically included from other header files. | 12 // singled out because it is most typically included from other header files. |
| 13 #import <Foundation/NSObject.h> | 13 #import <Foundation/NSObject.h> |
| 14 | 14 |
| 15 #include "base/compiler_specific.h" | 15 #include "base/compiler_specific.h" |
| 16 #include "base/mac/scoped_typeref.h" | 16 #include "base/mac/scoped_typeref.h" |
| 17 | 17 |
| 18 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 18 @class NSAutoreleasePool; | 19 @class NSAutoreleasePool; |
| 20 #endif | |
| 19 | 21 |
| 20 namespace base { | 22 namespace base { |
| 21 | 23 |
| 22 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership | 24 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership |
| 23 // of an NSObject subclass object. Style deviations here are solely for | 25 // of an NSObject subclass object. Style deviations here are solely for |
| 24 // compatibility with scoped_ptr<>'s interface, with which everyone is already | 26 // compatibility with scoped_ptr<>'s interface, with which everyone is already |
| 25 // familiar. | 27 // familiar. |
| 26 // | 28 // |
| 27 // scoped_nsobject<> takes ownership of an object (in the constructor or in | 29 // scoped_nsobject<> takes ownership of an object (in the constructor or in |
| 28 // reset()) by taking over the caller's existing ownership claim. The caller | 30 // reset()) by taking over the caller's existing ownership claim. The caller |
| 29 // must own the object it gives to scoped_nsobject<>, and relinquishes an | 31 // must own the object it gives to scoped_nsobject<>, and relinquishes an |
| 30 // ownership claim to that object. scoped_nsobject<> does not call -retain, | 32 // ownership claim to that object. scoped_nsobject<> does not call -retain, |
| 31 // callers have to call this manually if appropriate. | 33 // callers have to call this manually if appropriate. |
| 32 // | 34 // |
| 33 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used | 35 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used |
| 34 // with protocols. | 36 // with protocols. |
| 35 // | 37 // |
| 36 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For | 38 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For |
| 37 // NSAutoreleasePools use ScopedNSAutoreleasePool from | 39 // NSAutoreleasePools use ScopedNSAutoreleasePool from |
| 38 // scoped_nsautorelease_pool.h instead. | 40 // scoped_nsautorelease_pool.h instead. |
| 39 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile | 41 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile |
| 40 // time with a template specialization (see below). | 42 // time with a template specialization (see below). |
| 41 | 43 |
| 42 namespace internal { | 44 namespace internal { |
| 43 | 45 |
| 46 id ScopedNSProtocolTraitsRetain(__unsafe_unretained id obj) | |
| 47 __attribute((ns_returns_not_retained)); | |
| 48 id ScopedNSProtocolTraitsAutoRelease(__unsafe_unretained id obj) | |
| 49 __attribute((ns_returns_not_retained)); | |
| 50 void ScopedNSProtocolTraitsRelease(__unsafe_unretained id obj); | |
| 51 | |
| 44 template <typename NST> | 52 template <typename NST> |
| 45 struct ScopedNSProtocolTraits { | 53 struct ScopedNSProtocolTraits { |
| 46 static NST InvalidValue() { return nil; } | 54 static NST InvalidValue() __attribute((ns_returns_not_retained)) { |
|
Nico
2016/04/04 17:53:45
is this one needed? [nil retain] is a noop, right?
| |
| 47 static NST Retain(NST nst) { return [nst retain]; } | 55 return nil; |
| 48 static void Release(NST nst) { [nst release]; } | 56 } |
| 57 static NST Retain(__unsafe_unretained NST nst) | |
|
Nico
2016/04/04 17:53:45
`Retain() returns_not_retained` needs a comment on
| |
| 58 __attribute((ns_returns_not_retained)) { | |
| 59 return ScopedNSProtocolTraitsRetain(nst); | |
| 60 } | |
| 61 static void Release(__unsafe_unretained NST nst) { | |
| 62 ScopedNSProtocolTraitsRelease(nst); | |
| 63 } | |
| 49 }; | 64 }; |
| 50 | 65 |
| 51 } // namespace internal | 66 } // namespace internal |
| 52 | 67 |
| 53 template <typename NST> | 68 template <typename NST> |
| 54 class scoped_nsprotocol | 69 class scoped_nsprotocol |
| 55 : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> { | 70 : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> { |
| 56 public: | 71 public: |
| 57 using ScopedTypeRef<NST, | 72 using ScopedTypeRef<NST, |
| 58 internal::ScopedNSProtocolTraits<NST>>::ScopedTypeRef; | 73 internal::ScopedNSProtocolTraits<NST>>::ScopedTypeRef; |
| 59 | 74 |
| 60 // Shift reference to the autorelease pool to be released later. | 75 // Shift reference to the autorelease pool to be released later. |
| 61 NST autorelease() { return [this->release() autorelease]; } | 76 NST autorelease() __attribute((ns_returns_not_retained)) { |
| 77 return internal::ScopedNSProtocolTraitsAutoRelease(this->release()); | |
| 78 } | |
| 62 }; | 79 }; |
| 63 | 80 |
| 64 // Free functions | 81 // Free functions |
| 65 template <class C> | 82 template <class C> |
| 66 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) { | 83 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) { |
| 67 p1.swap(p2); | 84 p1.swap(p2); |
| 68 } | 85 } |
| 69 | 86 |
| 70 template <class C> | 87 template <class C> |
| 71 bool operator==(C p1, const scoped_nsprotocol<C>& p2) { | 88 bool operator==(C p1, const scoped_nsprotocol<C>& p2) { |
| 72 return p1 == p2.get(); | 89 return p1 == p2.get(); |
| 73 } | 90 } |
| 74 | 91 |
| 75 template <class C> | 92 template <class C> |
| 76 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { | 93 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { |
| 77 return p1 != p2.get(); | 94 return p1 != p2.get(); |
| 78 } | 95 } |
| 79 | 96 |
| 80 template <typename NST> | 97 template <typename NST> |
| 81 class scoped_nsobject : public scoped_nsprotocol<NST*> { | 98 class scoped_nsobject : public scoped_nsprotocol<NST*> { |
|
Nico
2016/04/04 17:53:45
in arc mode, you probably want to add a static_ass
| |
| 82 public: | 99 public: |
| 83 using scoped_nsprotocol<NST*>::scoped_nsprotocol; | 100 using scoped_nsprotocol<NST*>::scoped_nsprotocol; |
| 84 | 101 |
| 102 #if !defined(__has_feature) || !__has_feature(objc_arc) | |
| 85 static_assert(std::is_same<NST, NSAutoreleasePool>::value == false, | 103 static_assert(std::is_same<NST, NSAutoreleasePool>::value == false, |
| 86 "Use ScopedNSAutoreleasePool instead"); | 104 "Use ScopedNSAutoreleasePool instead"); |
| 105 #endif | |
| 87 }; | 106 }; |
| 88 | 107 |
| 89 // Specialization to make scoped_nsobject<id> work. | 108 // Specialization to make scoped_nsobject<id> work. |
| 90 template<> | 109 template<> |
| 91 class scoped_nsobject<id> : public scoped_nsprotocol<id> { | 110 class scoped_nsobject<id> : public scoped_nsprotocol<id> { |
| 92 public: | 111 public: |
| 93 using scoped_nsprotocol<id>::scoped_nsprotocol; | 112 using scoped_nsprotocol<id>::scoped_nsprotocol; |
| 94 }; | 113 }; |
| 95 | 114 |
| 96 } // namespace base | 115 } // namespace base |
| 97 | 116 |
| 98 #endif // BASE_MAC_SCOPED_NSOBJECT_H_ | 117 #endif // BASE_MAC_SCOPED_NSOBJECT_H_ |
| OLD | NEW |