Chromium Code Reviews| 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(): | |
|
darin (slow to review)
2011/10/14 21:53:07
nit: new line below this line as you did for Unret
awong
2011/10/15 00:19:16
Done. Also fixed ConstRef and IgnoreReturn.
| |
| 41 // void foo(int* arg) { cout << *arg << endl } | |
| 42 // | |
| 43 // int* pn = new int(1); | |
| 44 // Closure foo_callback = Bind(&foo, Owned(pn)); | |
| 45 // | |
| 46 // foo_callback.Run(); // Prints "1" | |
| 47 // foo_callback.Run(); // Prints "1" | |
| 48 // *n = 2; | |
| 49 // foo_callback.Run(); // Prints "2" | |
| 50 // | |
| 51 // foo_callback.Reset(); // |pn| is deleted. Also will happen when | |
| 52 // // |foo_callback| goes out of scope. | |
| 53 // | |
| 54 // Without Owned(), someone would have to know to delete |pn| when the last | |
| 55 // reference to the Callback is deleted. | |
| 56 // | |
| 57 // | |
| 37 // EXAMPLE OF ConstRef(): | 58 // EXAMPLE OF ConstRef(): |
| 38 // void foo(int arg) { cout << arg << endl } | 59 // void foo(int arg) { cout << arg << endl } |
| 39 // | 60 // |
| 40 // int n = 1; | 61 // int n = 1; |
| 41 // Callback<void(void)> no_ref = Bind(&foo, n); | 62 // Closure no_ref = Bind(&foo, n); |
| 42 // Callback<void(void)> has_ref = Bind(&foo, ConstRef(n)); | 63 // Closure has_ref = Bind(&foo, ConstRef(n)); |
| 43 // | 64 // |
| 44 // no_ref.Run(); // Prints "1" | 65 // no_ref.Run(); // Prints "1" |
| 45 // has_ref.Run(); // Prints "1" | 66 // has_ref.Run(); // Prints "1" |
| 46 // | 67 // |
| 47 // n = 2; | 68 // n = 2; |
| 48 // no_ref.Run(); // Prints "1" | 69 // no_ref.Run(); // Prints "1" |
| 49 // has_ref.Run(); // Prints "2" | 70 // has_ref.Run(); // Prints "2" |
| 50 // | 71 // |
| 51 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all | 72 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all |
| 52 // its bound callbacks. | 73 // its bound callbacks. |
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 192 | 213 |
| 193 template <typename T> | 214 template <typename T> |
| 194 struct UnsafeBindtoRefCountedArg<T*> | 215 struct UnsafeBindtoRefCountedArg<T*> |
| 195 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { | 216 : UnsafeBindtoRefCountedArgHelper<is_class<T>::value, T> { |
| 196 }; | 217 }; |
| 197 | 218 |
| 198 | 219 |
| 199 template <typename T> | 220 template <typename T> |
| 200 class UnretainedWrapper { | 221 class UnretainedWrapper { |
| 201 public: | 222 public: |
| 202 explicit UnretainedWrapper(T* o) : obj_(o) {} | 223 explicit UnretainedWrapper(T* o) : ptr_(o) {} |
| 203 T* get() { return obj_; } | 224 T* get() const { return ptr_; } |
| 204 private: | 225 private: |
| 205 T* obj_; | 226 T* ptr_; |
| 206 }; | 227 }; |
| 207 | 228 |
| 208 template <typename T> | 229 template <typename T> |
| 209 class ConstRefWrapper { | 230 class ConstRefWrapper { |
| 210 public: | 231 public: |
| 211 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} | 232 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} |
| 212 const T& get() { return *ptr_; } | 233 const T& get() const { return *ptr_; } |
| 213 private: | 234 private: |
| 214 const T* ptr_; | 235 const T* ptr_; |
| 215 }; | 236 }; |
| 216 | 237 |
| 238 // An alternate implementation is to avoid the destructive copy, and instead | |
| 239 // specialize ParamTraits<> for OwnedWrapper<> to change the StorageType to | |
| 240 // a class that is essentially a scoped_ptr<>. | |
| 241 // | |
| 242 // This has the benefit though of leaving ParamTrais<> fully in | |
|
darin (slow to review)
2011/10/14 21:53:07
nit: ParamTrais -> ParamTraits
awong
2011/10/15 00:19:16
Done.
| |
| 243 // callback_internal.h as well as avoiding type conversions during storage. | |
| 244 template <typename T> | |
| 245 class OwnedWrapper { | |
| 246 public: | |
| 247 explicit OwnedWrapper(T* o) : ptr_(o) {} | |
| 248 ~OwnedWrapper() { delete ptr_; } | |
| 249 T* get() const { return ptr_; } | |
| 250 OwnedWrapper(const OwnedWrapper& other) { | |
| 251 ptr_ = other.ptr_; | |
| 252 other.ptr_ = NULL; | |
| 253 } | |
| 254 | |
| 255 private: | |
| 256 mutable T* ptr_; | |
| 257 }; | |
| 258 | |
| 217 | 259 |
| 218 // Unwrap the stored parameters for the wrappers above. | 260 // Unwrap the stored parameters for the wrappers above. |
| 219 template <typename T> | 261 template <typename T> |
| 220 T Unwrap(T o) { return o; } | 262 T Unwrap(T o) { return o; } |
| 221 | 263 |
| 222 template <typename T> | 264 template <typename T> |
| 223 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } | 265 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } |
| 224 | 266 |
| 225 template <typename T> | 267 template <typename T> |
| 226 const T& Unwrap(ConstRefWrapper<T> const_ref) { | 268 const T& Unwrap(ConstRefWrapper<T> const_ref) { |
| 227 return const_ref.get(); | 269 return const_ref.get(); |
| 228 } | 270 } |
| 229 | 271 |
| 230 template <typename T> | 272 template <typename T> |
| 231 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } | 273 T* Unwrap(const scoped_refptr<T>& o) { return o.get(); } |
| 232 | 274 |
| 233 template <typename T> | 275 template <typename T> |
| 234 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } | 276 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { return o; } |
| 235 | 277 |
| 278 template <typename T> | |
| 279 T* Unwrap(const OwnedWrapper<T>& o) { | |
| 280 return o.get(); | |
| 281 } | |
| 282 | |
| 236 // Utility for handling different refcounting semantics in the Bind() | 283 // Utility for handling different refcounting semantics in the Bind() |
| 237 // function. | 284 // function. |
| 238 template <typename IsMethod, typename T> | 285 template <typename IsMethod, typename T> |
| 239 struct MaybeRefcount; | 286 struct MaybeRefcount; |
| 240 | 287 |
| 241 template <typename T> | 288 template <typename T> |
| 242 struct MaybeRefcount<base::false_type, T> { | 289 struct MaybeRefcount<base::false_type, T> { |
| 243 static void AddRef(const T&) {} | 290 static void AddRef(const T&) {} |
| 244 static void Release(const T&) {} | 291 static void Release(const T&) {} |
| 245 }; | 292 }; |
| 246 | 293 |
| 247 template <typename T, size_t n> | 294 template <typename T, size_t n> |
| 248 struct MaybeRefcount<base::false_type, T[n]> { | 295 struct MaybeRefcount<base::false_type, T[n]> { |
| 249 static void AddRef(const T*) {} | 296 static void AddRef(const T*) {} |
| 250 static void Release(const T*) {} | 297 static void Release(const T*) {} |
| 251 }; | 298 }; |
| 252 | 299 |
| 253 template <typename T> | 300 template <typename T> |
| 301 struct MaybeRefcount<base::true_type, T*> { | |
| 302 static void AddRef(T* o) { o->AddRef(); } | |
| 303 static void Release(T* o) { o->Release(); } | |
| 304 }; | |
| 305 | |
| 306 template <typename T> | |
| 254 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { | 307 struct MaybeRefcount<base::true_type, UnretainedWrapper<T> > { |
| 255 static void AddRef(const UnretainedWrapper<T>&) {} | 308 static void AddRef(const UnretainedWrapper<T>&) {} |
| 256 static void Release(const UnretainedWrapper<T>&) {} | 309 static void Release(const UnretainedWrapper<T>&) {} |
| 257 }; | 310 }; |
| 258 | 311 |
| 259 template <typename T> | 312 template <typename T> |
| 260 struct MaybeRefcount<base::true_type, T*> { | 313 struct MaybeRefcount<base::true_type, OwnedWrapper<T> > { |
| 261 static void AddRef(T* o) { o->AddRef(); } | 314 static void AddRef(const OwnedWrapper<T>&) {} |
| 262 static void Release(T* o) { o->Release(); } | 315 static void Release(const OwnedWrapper<T>&) {} |
| 263 }; | 316 }; |
| 264 | 317 |
| 265 // No need to additionally AddRef() and Release() since we are storing a | 318 // No need to additionally AddRef() and Release() since we are storing a |
| 266 // scoped_refptr<> inside the storage object already. | 319 // scoped_refptr<> inside the storage object already. |
| 267 template <typename T> | 320 template <typename T> |
| 268 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { | 321 struct MaybeRefcount<base::true_type, scoped_refptr<T> > { |
| 269 static void AddRef(const scoped_refptr<T>& o) {} | 322 static void AddRef(const scoped_refptr<T>& o) {} |
| 270 static void Release(const scoped_refptr<T>& o) {} | 323 static void Release(const scoped_refptr<T>& o) {} |
| 271 }; | 324 }; |
| 272 | 325 |
| (...skipping 19 matching lines...) Expand all Loading... | |
| 292 template <typename T> | 345 template <typename T> |
| 293 inline internal::UnretainedWrapper<T> Unretained(T* o) { | 346 inline internal::UnretainedWrapper<T> Unretained(T* o) { |
| 294 return internal::UnretainedWrapper<T>(o); | 347 return internal::UnretainedWrapper<T>(o); |
| 295 } | 348 } |
| 296 | 349 |
| 297 template <typename T> | 350 template <typename T> |
| 298 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { | 351 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { |
| 299 return internal::ConstRefWrapper<T>(o); | 352 return internal::ConstRefWrapper<T>(o); |
| 300 } | 353 } |
| 301 | 354 |
| 355 template <typename T> | |
| 356 inline internal::OwnedWrapper<T> Owned(T* o) { | |
| 357 return internal::OwnedWrapper<T>(o); | |
| 358 } | |
| 359 | |
| 302 template <typename R> | 360 template <typename R> |
| 303 Closure IgnoreReturn(Callback<R(void)> callback) { | 361 Closure IgnoreReturn(Callback<R(void)> callback) { |
| 304 return Bind(&internal::VoidReturnAdapter<R>, callback); | 362 return Bind(&internal::VoidReturnAdapter<R>, callback); |
| 305 } | 363 } |
| 306 | 364 |
| 307 } // namespace base | 365 } // namespace base |
| 308 | 366 |
| 309 #endif // BASE_BIND_HELPERS_H_ | 367 #endif // BASE_BIND_HELPERS_H_ |
| OLD | NEW |