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_MEMORY_SCOPED_NSOBJECT_H_ | 5 #ifndef BASE_MEMORY_SCOPED_NSOBJECT_H_ |
6 #define BASE_MEMORY_SCOPED_NSOBJECT_H_ | 6 #define BASE_MEMORY_SCOPED_NSOBJECT_H_ |
7 | 7 |
8 #import <Foundation/Foundation.h> | 8 #import <Foundation/Foundation.h> |
9 #include "base/basictypes.h" | 9 #include "base/basictypes.h" |
10 #include "base/compiler_specific.h" | 10 #include "base/compiler_specific.h" |
11 #include "base/memory/scoped_policy.h" | |
12 | 11 |
13 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership | 12 // scoped_nsobject<> is patterned after scoped_ptr<>, but maintains ownership |
14 // of an NSObject subclass object. Style deviations here are solely for | 13 // of an NSObject subclass object. Style deviations here are solely for |
15 // compatibility with scoped_ptr<>'s interface, with which everyone is already | 14 // compatibility with scoped_ptr<>'s interface, with which everyone is already |
16 // familiar. | 15 // familiar. |
17 // | 16 // |
18 // By default, scoped_nsobject<> takes ownership of an object (in the | 17 // scoped_nsobject<> takes ownership of an object (in the constructor or in |
19 // constructor or in reset()) by taking over the caller's existing ownership | 18 // reset()) by taking over the caller's existing ownership claim. The caller |
20 // claim. The caller must own the object it gives to scoped_nsobject<>, and | 19 // must own the object it gives to scoped_nsobject<>, and relinquishes an |
21 // relinquishes an ownership claim to that object. scoped_nsobject<> does not | 20 // ownership claim to that object. scoped_nsobject<> does not call -retain, |
22 // call -retain. This behavior is parametrized by the |OwnershipPolicy| enum. | 21 // callers have to call this manually if appropriate. |
23 // If the value |RETAIN| is passed (in the constructor or in reset()), then | |
24 // scoped_nsobject<> will call -retain on the object, and the initial | |
25 // ownership is not changed. | |
26 // | 22 // |
27 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used | 23 // scoped_nsprotocol<> has the same behavior as scoped_nsobject, but can be used |
28 // with protocols. | 24 // with protocols. |
29 // | 25 // |
30 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For | 26 // scoped_nsobject<> is not to be used for NSAutoreleasePools. For |
31 // NSAutoreleasePools use ScopedNSAutoreleasePool from | 27 // NSAutoreleasePools use ScopedNSAutoreleasePool from |
32 // scoped_nsautorelease_pool.h instead. | 28 // scoped_nsautorelease_pool.h instead. |
33 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile | 29 // We check for bad uses of scoped_nsobject and NSAutoreleasePool at compile |
34 // time with a template specialization (see below). | 30 // time with a template specialization (see below). |
35 | 31 |
36 template<typename NST> | 32 template<typename NST> |
37 class scoped_nsprotocol { | 33 class scoped_nsprotocol { |
38 public: | 34 public: |
39 explicit scoped_nsprotocol( | 35 explicit scoped_nsprotocol(NST object = nil) : object_(object) {} |
40 NST object = nil, | |
41 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) | |
42 : object_(object) { | |
43 if (policy == base::scoped_policy::RETAIN) | |
44 [object retain]; | |
45 } | |
46 | 36 |
47 scoped_nsprotocol(const scoped_nsprotocol<NST>& that) | 37 scoped_nsprotocol(const scoped_nsprotocol<NST>& that) |
48 : object_([that.object_ retain]) { | 38 : object_([that.object_ retain]) { |
49 } | 39 } |
50 | 40 |
51 ~scoped_nsprotocol() { | 41 ~scoped_nsprotocol() { |
52 [object_ release]; | 42 [object_ release]; |
53 } | 43 } |
54 | 44 |
55 scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) { | 45 scoped_nsprotocol& operator=(const scoped_nsprotocol<NST>& that) { |
56 reset(that.get(), base::scoped_policy::RETAIN); | 46 reset([that.get() retain]); |
57 return *this; | 47 return *this; |
58 } | 48 } |
59 | 49 |
60 void reset(NST object = nil, | 50 void reset(NST object = nil) { |
61 base::scoped_policy::OwnershipPolicy policy = | |
62 base::scoped_policy::ASSUME) { | |
63 if (policy == base::scoped_policy::RETAIN) | |
64 [object retain]; | |
65 // We intentionally do not check that object != object_ as the caller must | 51 // We intentionally do not check that object != object_ as the caller must |
66 // either already have an ownership claim over whatever it passes to this | 52 // either already have an ownership claim over whatever it passes to this |
67 // method, or call it with the |RETAIN| policy which will have ensured that | 53 // method, or call it with the |RETAIN| policy which will have ensured that |
68 // the object is retained once more when reaching this point. | 54 // the object is retained once more when reaching this point. |
69 [object_ release]; | 55 [object_ release]; |
70 object_ = object; | 56 object_ = object; |
71 } | 57 } |
72 | 58 |
73 bool operator==(NST that) const { return object_ == that; } | 59 bool operator==(NST that) const { return object_ == that; } |
74 bool operator!=(NST that) const { return object_ != that; } | 60 bool operator!=(NST that) const { return object_ != that; } |
(...skipping 42 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
117 } | 103 } |
118 | 104 |
119 template <class C> | 105 template <class C> |
120 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { | 106 bool operator!=(C p1, const scoped_nsprotocol<C>& p2) { |
121 return p1 != p2.get(); | 107 return p1 != p2.get(); |
122 } | 108 } |
123 | 109 |
124 template<typename NST> | 110 template<typename NST> |
125 class scoped_nsobject : public scoped_nsprotocol<NST*> { | 111 class scoped_nsobject : public scoped_nsprotocol<NST*> { |
126 public: | 112 public: |
127 explicit scoped_nsobject( | 113 explicit scoped_nsobject(NST* object = nil) |
128 NST* object = nil, | 114 : scoped_nsprotocol<NST*>(object) {} |
129 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) | |
130 : scoped_nsprotocol<NST*>(object, policy) { | |
131 } | |
132 | 115 |
133 scoped_nsobject(const scoped_nsobject<NST>& that) | 116 scoped_nsobject(const scoped_nsobject<NST>& that) |
134 : scoped_nsprotocol<NST*>(that) { | 117 : scoped_nsprotocol<NST*>(that) { |
135 } | 118 } |
136 | 119 |
137 scoped_nsobject& operator=(const scoped_nsobject<NST>& that) { | 120 scoped_nsobject& operator=(const scoped_nsobject<NST>& that) { |
138 scoped_nsprotocol<NST*>::operator=(that); | 121 scoped_nsprotocol<NST*>::operator=(that); |
139 return *this; | 122 return *this; |
140 } | 123 } |
141 }; | 124 }; |
142 | 125 |
143 // Specialization to make scoped_nsobject<id> work. | 126 // Specialization to make scoped_nsobject<id> work. |
144 template<> | 127 template<> |
145 class scoped_nsobject<id> : public scoped_nsprotocol<id> { | 128 class scoped_nsobject<id> : public scoped_nsprotocol<id> { |
146 public: | 129 public: |
147 explicit scoped_nsobject( | 130 explicit scoped_nsobject(id object = nil) : scoped_nsprotocol<id>(object) {} |
148 id object = nil, | |
149 base::scoped_policy::OwnershipPolicy policy = base::scoped_policy::ASSUME) | |
150 : scoped_nsprotocol<id>(object, policy) { | |
151 } | |
152 | 131 |
153 scoped_nsobject(const scoped_nsobject<id>& that) | 132 scoped_nsobject(const scoped_nsobject<id>& that) |
154 : scoped_nsprotocol<id>(that) { | 133 : scoped_nsprotocol<id>(that) { |
155 } | 134 } |
156 | 135 |
157 scoped_nsobject& operator=(const scoped_nsobject<id>& that) { | 136 scoped_nsobject& operator=(const scoped_nsobject<id>& that) { |
158 scoped_nsprotocol<id>::operator=(that); | 137 scoped_nsprotocol<id>::operator=(that); |
159 return *this; | 138 return *this; |
160 } | 139 } |
161 }; | 140 }; |
162 | 141 |
163 // Do not use scoped_nsobject for NSAutoreleasePools, use | 142 // Do not use scoped_nsobject for NSAutoreleasePools, use |
164 // ScopedNSAutoreleasePool instead. This is a compile time check. See details | 143 // ScopedNSAutoreleasePool instead. This is a compile time check. See details |
165 // at top of header. | 144 // at top of header. |
166 template<> | 145 template<> |
167 class scoped_nsobject<NSAutoreleasePool> { | 146 class scoped_nsobject<NSAutoreleasePool> { |
168 private: | 147 private: |
169 explicit scoped_nsobject(NSAutoreleasePool* object = nil, | 148 explicit scoped_nsobject(NSAutoreleasePool* object = nil); |
170 base::scoped_policy::OwnershipPolicy policy = | |
171 base::scoped_policy::ASSUME); | |
172 DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); | 149 DISALLOW_COPY_AND_ASSIGN(scoped_nsobject); |
173 }; | 150 }; |
174 #endif // BASE_MEMORY_SCOPED_NSOBJECT_H_ | 151 #endif // BASE_MEMORY_SCOPED_NSOBJECT_H_ |
OLD | NEW |