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 |