OLD | NEW |
1 // Copyright (c) 2011 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2011 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 // This defines a set of argument wrappers and related factory methods that | 5 // This defines a set of argument wrappers and related factory methods that |
6 // can be used specify the refcounting and reference semantics of arguments | 6 // can be used specify the refcounting and reference semantics of arguments |
7 // that are bound by the Bind() function in base/bind.h. | 7 // that are bound by the Bind() function in base/bind.h. |
8 // | 8 // |
9 // The public functions are base::Unretained(), base::ConstRef(), and | 9 // The public functions are base::Unretained(), base::Owned(), |
10 // base::IgnoreReturn(). | 10 // base::ConstRef(), and base::IgnoreReturn(). |
11 // | 11 // |
12 // Unretained() allows Bind() to bind a non-refcounted class. | 12 // Unretained() allows Bind() to bind a non-refcounted class, and to disable |
| 13 // refcounting on arguments that are refcounted objects. |
| 14 // Owned() transfers ownership of an object to the Callback resulting from |
| 15 // bind; the object will be deleted when the Callback is deleted. |
13 // ConstRef() allows binding a constant reference to an argument rather | 16 // ConstRef() allows binding a constant reference to an argument rather |
14 // than a copy. | 17 // than a copy. |
15 // IgnoreReturn() is used to adapt a 0-argument Callback with a return type to | 18 // IgnoreReturn() is used to adapt a 0-argument Callback with a return type to |
16 // a Closure. This is useful if you need to PostTask with a function that has | 19 // a Closure. This is useful if you need to PostTask with a function that has |
17 // a return value that you don't care about. | 20 // a return value that you don't care about. |
18 // | 21 // |
19 // | 22 // |
20 // EXAMPLE OF Unretained(): | 23 // EXAMPLE OF Unretained(): |
21 // | 24 // |
22 // class Foo { | 25 // class Foo { |
23 // public: | 26 // public: |
24 // void func() { cout << "Foo:f" << endl; } | 27 // void func() { cout << "Foo:f" << endl; } |
25 // }; | 28 // }; |
26 // | 29 // |
27 // // In some function somewhere. | 30 // // In some function somewhere. |
28 // Foo foo; | 31 // Foo foo; |
29 // Callback<void(void)> foo_callback = | 32 // Closure foo_callback = |
30 // Bind(&Foo::func, Unretained(&foo)); | 33 // Bind(&Foo::func, Unretained(&foo)); |
31 // foo_callback.Run(); // Prints "Foo:f". | 34 // foo_callback.Run(); // Prints "Foo:f". |
32 // | 35 // |
33 // Without the Unretained() wrapper on |&foo|, the above call would fail | 36 // Without the Unretained() wrapper on |&foo|, the above call would fail |
34 // to compile because Foo does not support the AddRef() and Release() methods. | 37 // to compile because Foo does not support the AddRef() and Release() methods. |
35 // | 38 // |
36 // | 39 // |
| 40 // EXAMPLE OF Owned(): |
| 41 // |
| 42 // void foo(int* arg) { cout << *arg << endl } |
| 43 // |
| 44 // int* pn = new int(1); |
| 45 // Closure foo_callback = Bind(&foo, Owned(pn)); |
| 46 // |
| 47 // foo_callback.Run(); // Prints "1" |
| 48 // foo_callback.Run(); // Prints "1" |
| 49 // *n = 2; |
| 50 // foo_callback.Run(); // Prints "2" |
| 51 // |
| 52 // foo_callback.Reset(); // |pn| is deleted. Also will happen when |
| 53 // // |foo_callback| goes out of scope. |
| 54 // |
| 55 // Without Owned(), someone would have to know to delete |pn| when the last |
| 56 // reference to the Callback is deleted. |
| 57 // |
| 58 // |
37 // EXAMPLE OF ConstRef(): | 59 // EXAMPLE OF ConstRef(): |
| 60 // |
38 // void foo(int arg) { cout << arg << endl } | 61 // void foo(int arg) { cout << arg << endl } |
39 // | 62 // |
40 // int n = 1; | 63 // int n = 1; |
41 // Callback<void(void)> no_ref = Bind(&foo, n); | 64 // Closure no_ref = Bind(&foo, n); |
42 // Callback<void(void)> has_ref = Bind(&foo, ConstRef(n)); | 65 // Closure has_ref = Bind(&foo, ConstRef(n)); |
43 // | 66 // |
44 // no_ref.Run(); // Prints "1" | 67 // no_ref.Run(); // Prints "1" |
45 // has_ref.Run(); // Prints "1" | 68 // has_ref.Run(); // Prints "1" |
46 // | 69 // |
47 // n = 2; | 70 // n = 2; |
48 // no_ref.Run(); // Prints "1" | 71 // no_ref.Run(); // Prints "1" |
49 // has_ref.Run(); // Prints "2" | 72 // has_ref.Run(); // Prints "2" |
50 // | 73 // |
51 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all | 74 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all |
52 // its bound callbacks. | 75 // its bound callbacks. |
53 // | 76 // |
54 // | 77 // |
55 // EXAMPLE OF IgnoreReturn(): | 78 // EXAMPLE OF IgnoreReturn(): |
| 79 // |
56 // int DoSomething(int arg) { cout << arg << endl; } | 80 // int DoSomething(int arg) { cout << arg << endl; } |
57 // Callback<int(void)> cb = Bind(&DoSomething, 1); | 81 // Callback<int(void)> cb = Bind(&DoSomething, 1); |
58 // Closure c = IgnoreReturn(cb); // Prints "1" | 82 // Closure c = IgnoreReturn(cb); // Prints "1" |
59 // or | 83 // or |
60 // ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml| | 84 // ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml| |
61 | 85 |
62 #ifndef BASE_BIND_HELPERS_H_ | 86 #ifndef BASE_BIND_HELPERS_H_ |
63 #define BASE_BIND_HELPERS_H_ | 87 #define BASE_BIND_HELPERS_H_ |
64 #pragma once | 88 #pragma once |
65 | 89 |
(...skipping 126 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
192 | 216 |
193 template <typename T> | 217 template <typename T> |
194 struct UnsafeBindtoRefCountedArg<T*> | 218 struct UnsafeBindtoRefCountedArg<T*> |
195 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { | 219 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { |
196 }; | 220 }; |
197 | 221 |
198 | 222 |
199 template <typename T> | 223 template <typename T> |
200 class UnretainedWrapper { | 224 class UnretainedWrapper { |
201 public: | 225 public: |
202 explicit UnretainedWrapper(T* o) : obj_(o) {} | 226 explicit UnretainedWrapper(T* o) : ptr_(o) {} |
203 T* get() { return obj_; } | 227 T* get() const { return ptr_; } |
204 private: | 228 private: |
205 T* obj_; | 229 T* ptr_; |
206 }; | 230 }; |
207 | 231 |
208 template <typename T> | 232 template <typename T> |
209 class ConstRefWrapper { | 233 class ConstRefWrapper { |
210 public: | 234 public: |
211 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} | 235 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} |
212 const T& get() { return *ptr_; } | 236 const T& get() const { return *ptr_; } |
213 private: | 237 private: |
214 const T* ptr_; | 238 const T* ptr_; |
215 }; | 239 }; |
216 | 240 |
| 241 // An alternate implementation is to avoid the destructive copy, and instead |
| 242 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to |
| 243 // a class that is essentially a scoped_ptr<>. |
| 244 // |
| 245 // The current implementation has the benefit though of leaving ParamTraits<> |
| 246 // fully in callback_internal.h as well as avoiding type conversions during |
| 247 // storage. |
| 248 template <typename T> |
| 249 class OwnedWrapper { |
| 250 public: |
| 251 explicit OwnedWrapper(T* o) : ptr_(o) {} |
| 252 ~OwnedWrapper() { delete ptr_; } |
| 253 T* get() const { return ptr_; } |
| 254 OwnedWrapper(const OwnedWrapper& other) { |
| 255 ptr_ = other.ptr_; |
| 256 other.ptr_ = NULL; |
| 257 } |
| 258 |
| 259 private: |
| 260 mutable T* ptr_; |
| 261 }; |
| 262 |
217 | 263 |
218 // Unwrap the stored parameters for the wrappers above. | 264 // Unwrap the stored parameters for the wrappers above. |
219 template <typename T> | 265 template <typename T> |
220 T Unwrap(T o) { return o; } | 266 T Unwrap(T o) { return o; } |
221 | 267 |
222 template <typename T> | 268 template <typename T> |
223 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } | 269 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } |
224 | 270 |
225 template <typename T> | 271 template <typename T> |
226 const T& Unwrap(ConstRefWrapper<T> const_ref) { | 272 const T& Unwrap(ConstRefWrapper<T> const_ref) { |
227 return const_ref.get(); | 273 return const_ref.get(); |
228 } | 274 } |
229 | 275 |
230 template <typename T> | 276 template <typename T> |
231 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } | 277 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } |
232 | 278 |
233 template <typename T> | 279 template <typename T> |
234 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } | 280 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } |
235 | 281 |
| 282 template <typename T> |
| 283 T* Unwrap(const OwnedWrapper<T>& o) { |
| 284 return o.get(); |
| 285 } |
| 286 |
236 // Utility for handling different refcounting semantics in the Bind() | 287 // Utility for handling different refcounting semantics in the Bind() |
237 // function. | 288 // function. |
238 template <typename IsMethod, typename T> | 289 template <typename IsMethod, typename T> |
239 struct MaybeRefcount; | 290 struct MaybeRefcount; |
240 | 291 |
241 template <typename T> | 292 template <typename T> |
242 struct MaybeRefcount<base::false_type, T> { | 293 struct MaybeRefcount<base::false_type, T> { |
243 static void AddRef(const T&) {} | 294 static void AddRef(const T&) {} |
244 static void Release(const T&) {} | 295 static void Release(const T&) {} |
245 }; | 296 }; |
246 | 297 |
247 template <typename T, size_t n> | 298 template <typename T, size_t n> |
248 struct MaybeRefcount<base::false_type, T[n]> { | 299 struct MaybeRefcount<base::false_type, T[n]> { |
249 static void AddRef(const T*) {} | 300 static void AddRef(const T*) {} |
250 static void Release(const T*) {} | 301 static void Release(const T*) {} |
251 }; | 302 }; |
252 | 303 |
253 template <typename T> | 304 template <typename T> |
| 305 struct MaybeRefcount<base::true_type, T*> { |
| 306 static void AddRef(T* o) { o->AddRef(); } |
| 307 static void Release(T* o) { o->Release(); } |
| 308 }; |
| 309 |
| 310 template <typename T> |
254 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { | 311 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { |
255 static void AddRef(const UnretainedWrapper<T>&) {} | 312 static void AddRef(const UnretainedWrapper<T>&) {} |
256 static void Release(const UnretainedWrapper<T>&) {} | 313 static void Release(const UnretainedWrapper<T>&) {} |
257 }; | 314 }; |
258 | 315 |
259 template <typename T> | 316 template <typename T> |
260 struct MaybeRefcount<base::true_type, T*> { | 317 struct MaybeRefcount<base::true_type, OwnedWrapper<T> > { |
261 static void AddRef(T* o) { o->AddRef(); } | 318 static void AddRef(const OwnedWrapper<T>&) {} |
262 static void Release(T* o) { o->Release(); } | 319 static void Release(const OwnedWrapper<T>&) {} |
263 }; | 320 }; |
264 | 321 |
265 // No need to additionally AddRef() and Release() since we are storing a | 322 // No need to additionally AddRef() and Release() since we are storing a |
266 // scoped_refptr<> inside the storage object already. | 323 // scoped_refptr<> inside the storage object already. |
267 template <typename T> | 324 template <typename T> |
268 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { | 325 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { |
269 static void AddRef(const scoped_refptr<T>& o) {} | 326 static void AddRef(const scoped_refptr<T>& o) {} |
270 static void Release(const scoped_refptr<T>& o) {} | 327 static void Release(const scoped_refptr<T>& o) {} |
271 }; | 328 }; |
272 | 329 |
(...skipping 19 matching lines...) Expand all Loading... |
292 template <typename T> | 349 template <typename T> |
293 inline internal::UnretainedWrapper<T> Unretained(T* o) { | 350 inline internal::UnretainedWrapper<T> Unretained(T* o) { |
294 return internal::UnretainedWrapper<T>(o); | 351 return internal::UnretainedWrapper<T>(o); |
295 } | 352 } |
296 | 353 |
297 template <typename T> | 354 template <typename T> |
298 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { | 355 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { |
299 return internal::ConstRefWrapper<T>(o); | 356 return internal::ConstRefWrapper<T>(o); |
300 } | 357 } |
301 | 358 |
| 359 template <typename T> |
| 360 inline internal::OwnedWrapper<T> Owned(T* o) { |
| 361 return internal::OwnedWrapper<T>(o); |
| 362 } |
| 363 |
302 template <typename R> | 364 template <typename R> |
303 Closure IgnoreReturn(Callback<R(void)> callback) { | 365 Closure IgnoreReturn(Callback<R(void)> callback) { |
304 return Bind(&internal::VoidReturnAdapter<R>, callback); | 366 return Bind(&internal::VoidReturnAdapter<R>, callback); |
305 } | 367 } |
306 | 368 |
307 } // namespace base | 369 } // namespace base |
308 | 370 |
309 #endif // BASE_BIND_HELPERS_H_ | 371 #endif // BASE_BIND_HELPERS_H_ |
OLD | NEW |