Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(632)

Side by Side Diff: base/mac/scoped_nsobject.h

Issue 1855483004: [iOS/OS X] Allow base::scoped_nsobject<> to be used when ARC is enabled. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: Add missing copy constructor from scoped_nsobject<subclass> to scoped_nsobject<class> Created 4 years, 6 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/mac/scoped_block.h ('k') | base/mac/scoped_nsobject.mm » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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/base_export.h"
15 #include "base/compiler_specific.h" 16 #include "base/compiler_specific.h"
16 #include "base/mac/scoped_typeref.h" 17 #include "base/mac/scoped_typeref.h"
17 18
19 #if !defined(__has_feature) || !__has_feature(objc_arc)
18 @class NSAutoreleasePool; 20 @class NSAutoreleasePool;
21 #endif
19 22
20 namespace base { 23 namespace base {
21 24
22 // scoped_nsobject<> is patterned after std::unique_ptr<>, but maintains 25 // scoped_nsobject<> is patterned after std::unique_ptr<>, but maintains
23 // ownership of an NSObject subclass object. Style deviations here are solely 26 // ownership of an NSObject subclass object. Style deviations here are solely
24 // for compatibility with std::unique_ptr<>'s interface, with which everyone is 27 // for compatibility with std::unique_ptr<>'s interface, with which everyone is
25 // already familiar. 28 // already familiar.
26 // 29 //
27 // scoped_nsobject<> takes ownership of an object (in the constructor or in 30 // 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 31 // 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 32 // must own the object it gives to scoped_nsobject<>, and relinquishes an
30 // ownership claim to that object. scoped_nsobject<> does not call -retain, 33 // ownership claim to that object. scoped_nsobject<> does not call -retain,
31 // callers have to call this manually if appropriate. 34 // callers have to call this manually if appropriate.
32 // 35 //
33 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used 36 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used
34 // with protocols. 37 // with protocols.
35 // 38 //
36 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For 39 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For
37 // NSAutoreleasePools use ScopedNSAutoreleasePool from 40 // NSAutoreleasePools use ScopedNSAutoreleasePool from
38 // scoped_nsautorelease_pool.h instead. 41 // scoped_nsautorelease_pool.h instead.
39 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile 42 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile
40 // time with a template specialization (see below). 43 // time with a template specialization (see below).
44 //
45 // If Automatic Reference Counting (aka ARC) is enabled then the ownership
46 // policy is not controllable by the user as ARC make it really difficult to
47 // transfer ownership (the reference passed to scoped_nsobject constructor is
48 // sunk by ARC and __attribute((ns_consumed)) appears to not work correctly
49 // with Objective-C++ see https://llvm.org/bugs/show_bug.cgi?id=27887). Due to
50 // that, the policy is always to |RETAIN| when using ARC.
41 51
42 namespace internal { 52 namespace internal {
43 53
54 BASE_EXPORT id ScopedNSProtocolTraitsRetain(__unsafe_unretained id obj)
55 __attribute((ns_returns_not_retained));
56 BASE_EXPORT id ScopedNSProtocolTraitsAutoRelease(__unsafe_unretained id obj)
57 __attribute((ns_returns_not_retained));
58 BASE_EXPORT void ScopedNSProtocolTraitsRelease(__unsafe_unretained id obj);
59
60 // Traits for ScopedTypeRef<>. As this class may be compiled from file with
61 // Automatic Reference Counting enable or not all methods have annotation to
62 // enforce the same code generation in both case (in particular, the Retain
63 // method uses ns_returns_not_retained to prevent ARC to insert a -release
64 // call on the returned value and thus defeating the -retain).
44 template <typename NST> 65 template <typename NST>
45 struct ScopedNSProtocolTraits { 66 struct ScopedNSProtocolTraits {
46 static NST InvalidValue() { return nil; } 67 static NST InvalidValue() __attribute((ns_returns_not_retained)) {
47 static NST Retain(NST nst) { return [nst retain]; } 68 return nil;
48 static void Release(NST nst) { [nst release]; } 69 }
70 static NST Retain(__unsafe_unretained NST nst)
71 __attribute((ns_returns_not_retained)) {
72 return ScopedNSProtocolTraitsRetain(nst);
73 }
74 static void Release(__unsafe_unretained NST nst) {
75 ScopedNSProtocolTraitsRelease(nst);
76 }
49 }; 77 };
50 78
51 } // namespace internal 79 } // namespace internal
52 80
53 template <typename NST> 81 template <typename NST>
54 class scoped_nsprotocol 82 class scoped_nsprotocol
55 : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> { 83 : public ScopedTypeRef<NST, internal::ScopedNSProtocolTraits<NST>> {
56 public: 84 public:
57 using ScopedTypeRef<NST, 85 using Traits = internal::ScopedNSProtocolTraits<NST>;
58 internal::ScopedNSProtocolTraits<NST>>::ScopedTypeRef; 86
87 #if !defined(__has_feature) || !__has_feature(objc_arc)
88 explicit scoped_nsprotocol(
89 NST object = Traits::InvalidValue(),
90 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
91 : ScopedTypeRef<NST, Traits>(object, policy) {}
92 #else
93 explicit scoped_nsprotocol(NST object = Traits::InvalidValue())
94 : ScopedTypeRef<NST, Traits>(object, base::scoped_policy::RETAIN) {}
95 #endif
96
97 scoped_nsprotocol(const scoped_nsprotocol<NST>& that)
98 : ScopedTypeRef<NST, Traits>(that) {}
99
100 template <typename NSR>
101 explicit scoped_nsprotocol(const scoped_nsprotocol<NSR>& that_as_subclass)
102 : ScopedTypeRef<NST, Traits>(that_as_subclass) {}
103
104 scoped_nsprotocol(scoped_nsprotocol<NST>&& that)
105 : ScopedTypeRef<NST, Traits>(that) {}
106
107 scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) {
108 ScopedTypeRef<NST, Traits>::operator=(that);
109 return *this;
110 }
111
112 #if !defined(__has_feature) || !__has_feature(objc_arc)
113 void reset(NST object = Traits::InvalidValue(),
114 base::scoped_policy::OwnershipPolicy policy =
115 base::scoped_policy::ASSUME) {
116 ScopedTypeRef<NST, Traits>::reset(object, policy);
117 }
118 #else
119 void reset(NST object = Traits::InvalidValue()) {
120 ScopedTypeRef<NST, Traits>::reset(object, base::scoped_policy::RETAIN);
121 }
122 #endif
59 123
60 // Shift reference to the autorelease pool to be released later. 124 // Shift reference to the autorelease pool to be released later.
61 NST autorelease() { return [this->release() autorelease]; } 125 NST autorelease() __attribute((ns_returns_not_retained)) {
126 return internal::ScopedNSProtocolTraitsAutoRelease(this->release());
127 }
62 }; 128 };
63 129
64 // Free functions 130 // Free functions
65 template <class C> 131 template <class C>
66 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) { 132 void swap(scoped_nsprotocol<C>& p1, scoped_nsprotocol<C>& p2) {
67 p1.swap(p2); 133 p1.swap(p2);
68 } 134 }
69 135
70 template <class C> 136 template <class C>
71 bool operator==(C p1, const scoped_nsprotocol<C>& p2) { 137 bool operator==(C p1, const scoped_nsprotocol<C>& p2) {
72 return p1 == p2.get(); 138 return p1 == p2.get();
73 } 139 }
74 140
75 template <class C> 141 template <class C>
76 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { 142 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) {
77 return p1 != p2.get(); 143 return p1 != p2.get();
78 } 144 }
79 145
80 template <typename NST> 146 template <typename NST>
81 class scoped_nsobject : public scoped_nsprotocol<NST*> { 147 class scoped_nsobject : public scoped_nsprotocol<NST*> {
82 public: 148 public:
83 using scoped_nsprotocol<NST*>::scoped_nsprotocol; 149 using Traits = typename scoped_nsprotocol<NST*>::Traits;
84 150
151 #if !defined(__has_feature) || !__has_feature(objc_arc)
152 explicit scoped_nsobject(
153 NST* object = Traits::InvalidValue(),
154 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
155 : scoped_nsprotocol<NST*>(object, policy) {}
156 #else
157 explicit scoped_nsobject(NST* object = Traits::InvalidValue())
158 : scoped_nsprotocol<NST*>(object) {}
159 #endif
160
161 scoped_nsobject(const scoped_nsobject<NST>& that)
162 : scoped_nsprotocol<NST*>(that) {}
163
164 template <typename NSR>
165 explicit scoped_nsobject(const scoped_nsobject<NSR>& that_as_subclass)
166 : scoped_nsprotocol<NST*>(that_as_subclass) {}
167
168 scoped_nsobject(scoped_nsobject<NST>&& that)
169 : scoped_nsprotocol<NST*>(that) {}
170
171 scoped_nsobject& operator=(const scoped_nsobject<NST>& that) {
172 scoped_nsprotocol<NST*>::operator=(that);
173 return *this;
174 }
175
176 #if !defined(__has_feature) || !__has_feature(objc_arc)
177 void reset(NST* object = Traits::InvalidValue(),
178 base::scoped_policy::OwnershipPolicy policy =
179 base::scoped_policy::ASSUME) {
180 scoped_nsprotocol<NST*>::reset(object, policy);
181 }
182 #else
183 void reset(NST* object = Traits::InvalidValue()) {
184 scoped_nsprotocol<NST*>::reset(object);
185 }
186 #endif
187
188 #if !defined(__has_feature) || !__has_feature(objc_arc)
85 static_assert(std::is_same<NST, NSAutoreleasePool>::value == false, 189 static_assert(std::is_same<NST, NSAutoreleasePool>::value == false,
86 "Use ScopedNSAutoreleasePool instead"); 190 "Use ScopedNSAutoreleasePool instead");
191 #endif
87 }; 192 };
88 193
89 // Specialization to make scoped_nsobject<id> work. 194 // Specialization to make scoped_nsobject<id> work.
90 template<> 195 template<>
91 class scoped_nsobject<id> : public scoped_nsprotocol<id> { 196 class scoped_nsobject<id> : public scoped_nsprotocol<id> {
92 public: 197 public:
93 using scoped_nsprotocol<id>::scoped_nsprotocol; 198 using Traits = typename scoped_nsprotocol<id>::Traits;
199
200 #if !defined(__has_feature) || !__has_feature(objc_arc)
201 explicit scoped_nsobject(
202 id object = Traits::InvalidValue(),
203 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME)
204 : scoped_nsprotocol<id>(object, policy) {}
205 #else
206 explicit scoped_nsobject(id object = Traits::InvalidValue())
207 : scoped_nsprotocol<id>(object) {}
208 #endif
209
210 scoped_nsobject(const scoped_nsobject<id>& that)
211 : scoped_nsprotocol<id>(that) {}
212
213 template <typename NSR>
214 explicit scoped_nsobject(const scoped_nsobject<NSR>& that_as_subclass)
215 : scoped_nsprotocol<id>(that_as_subclass) {}
216
217 scoped_nsobject(scoped_nsobject<id>&& that) : scoped_nsprotocol<id>(that) {}
218
219 scoped_nsobject& operator=(const scoped_nsobject<id>& that) {
220 scoped_nsprotocol<id>::operator=(that);
221 return *this;
222 }
223
224 #if !defined(__has_feature) || !__has_feature(objc_arc)
225 void reset(id object = Traits::InvalidValue(),
226 base::scoped_policy::OwnershipPolicy policy =
227 base::scoped_policy::ASSUME) {
228 scoped_nsprotocol<id>::reset(object, policy);
229 }
230 #else
231 void reset(id object = Traits::InvalidValue()) {
232 scoped_nsprotocol<id>::reset(object);
233 }
234 #endif
94 }; 235 };
95 236
96 } // namespace base 237 } // namespace base
97 238
98 #endif // BASE_MAC_SCOPED_NSOBJECT_H_ 239 #endif // BASE_MAC_SCOPED_NSOBJECT_H_
OLDNEW
« no previous file with comments | « base/mac/scoped_block.h ('k') | base/mac/scoped_nsobject.mm » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698