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::Owned(), | 9 // The public functions are base::Unretained(), base::Owned(), bass::Passed(), |
10 // base::ConstRef(), and base::IgnoreReturn(). | 10 // base::ConstRef(), and base::IgnoreResult(). |
11 // | 11 // |
12 // Unretained() allows Bind() to bind a non-refcounted class, and to disable | 12 // Unretained() allows Bind() to bind a non-refcounted class, and to disable |
13 // refcounting on arguments that are refcounted objects. | 13 // refcounting on arguments that are refcounted objects. |
14 // | |
14 // Owned() transfers ownership of an object to the Callback resulting from | 15 // Owned() transfers ownership of an object to the Callback resulting from |
15 // bind; the object will be deleted when the Callback is deleted. | 16 // bind; the object will be deleted when the Callback is deleted. |
17 // | |
18 // Passed() is for transfering moveable-but-not-copyable types (eg. scoped_ptr) | |
willchan no longer on Chromium
2011/12/07 16:24:34
s/transfering/transferring/
s/moveable/movable/
awong
2011/12/08 21:04:10
Done.
| |
19 // through a Callback. Logically, this signifies a destructive transfer of | |
20 // the state of the argument into the target function. Invoking | |
21 // Callback::Run() twice on a Callback that was created with a Passed() | |
22 // argument will CHECK() because the first invocation would have already | |
23 // transfered ownership to the target function. | |
willchan no longer on Chromium
2011/12/07 16:24:34
s/transfered/transferred/
awong
2011/12/08 21:04:10
Done.
| |
24 // | |
16 // ConstRef() allows binding a constant reference to an argument rather | 25 // ConstRef() allows binding a constant reference to an argument rather |
17 // than a copy. | 26 // than a copy. |
18 // IgnoreReturn() is used to adapt a 0-argument Callback with a return type to | |
19 // a Closure. This is useful if you need to PostTask with a function that has | |
20 // a return value that you don't care about. | |
21 // | 27 // |
28 // IgnoreResult() is used to adapt a function or Callback with a return type to | |
29 // one with a void return. This is most useful if you have a function with, | |
30 // say, a pesky ignorable bool return that you want to use with PostTask or | |
31 // something else that expect a Callback with a void return. | |
22 // | 32 // |
23 // EXAMPLE OF Unretained(): | 33 // EXAMPLE OF Unretained(): |
24 // | 34 // |
25 // class Foo { | 35 // class Foo { |
26 // public: | 36 // public: |
27 // void func() { cout << "Foo:f" << endl; } | 37 // void func() { cout << "Foo:f" << endl; } |
28 // }; | 38 // }; |
29 // | 39 // |
30 // // In some function somewhere. | 40 // // In some function somewhere. |
31 // Foo foo; | 41 // Foo foo; |
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
68 // has_ref.Run(); // Prints "1" | 78 // has_ref.Run(); // Prints "1" |
69 // | 79 // |
70 // n = 2; | 80 // n = 2; |
71 // no_ref.Run(); // Prints "1" | 81 // no_ref.Run(); // Prints "1" |
72 // has_ref.Run(); // Prints "2" | 82 // has_ref.Run(); // Prints "2" |
73 // | 83 // |
74 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all | 84 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all |
75 // its bound callbacks. | 85 // its bound callbacks. |
76 // | 86 // |
77 // | 87 // |
78 // EXAMPLE OF IgnoreReturn(): | 88 // EXAMPLE OF IgnoreResult(): |
79 // | 89 // |
80 // int DoSomething(int arg) { cout << arg << endl; } | 90 // int DoSomething(int arg) { cout << arg << endl; } |
81 // Callback<int(void)> cb = Bind(&DoSomething, 1); | 91 // |
82 // Closure c = IgnoreReturn(cb); // Prints "1" | 92 // // Assign to a Callback with a void return type. |
83 // or | 93 // Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething)); |
84 // ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml| | 94 // cb->Run(1); // Prints "1". |
95 // | |
96 // // Prints "1" on |ml|. | |
97 // ml->PostTask(FROM_HERE, Bind(IgnoreResult(&DoSomething), 1); | |
98 // | |
99 // | |
100 // EXAMPLE OF Passed(): | |
101 // | |
102 // void TakesOwnership(scoped_ptr<Foo> arg) { } | |
103 // scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } | |
104 // | |
105 // scoped_ptr<Foo> f(new Foo()); | |
106 // | |
107 // // |cb| is given ownership of Foo(). |f| is now NULL. | |
108 // // You can use f.Pass() in place of &f, but it's more verbose. | |
109 // Closure cb = Bind(&TakesOwnership, Passed(&f)); | |
110 // | |
111 // // Run was never called so |cb| still owns Foo() and deletes | |
112 // // it on Reset(). | |
113 // cb.Reset(); | |
114 // | |
115 // // |cb| is given a new Foo created by CreateFoo(). | |
116 // cb = Bind(&TakesOwnership, Passed(CreateFoo())); | |
117 // | |
118 // // |arg| in TakesOwnership() is given ownership of Foo(). |cb| | |
119 // // no longers owns Foo() and, if reset, would not delete Foo(). | |
120 // cb.Run(); // Foo() is now transfered to |arg| and deleted. | |
willchan no longer on Chromium
2011/12/07 16:24:34
s/transfered/transferred/
awong
2011/12/08 21:04:10
Done.
| |
121 // cb.Run(); // This CHECK()s since Foo() already been used once. | |
willchan no longer on Chromium
2011/12/07 16:24:34
Is there actually a CHECK somewhere? Or does it SI
awong
2011/12/08 21:04:10
Yep. There's a distinction between initializing P
| |
122 // | |
123 // Passed() is particularly useful with PostTask() when you are transfering | |
124 // ownership of an argument into a task, but don't necessarily know if the | |
125 // task will always be executed. This can happen if the task is cancellable | |
126 // or if it is posted to a MessageLoopProxy. | |
85 | 127 |
86 #ifndef BASE_BIND_HELPERS_H_ | 128 #ifndef BASE_BIND_HELPERS_H_ |
87 #define BASE_BIND_HELPERS_H_ | 129 #define BASE_BIND_HELPERS_H_ |
88 #pragma once | 130 #pragma once |
89 | 131 |
90 #include "base/basictypes.h" | 132 #include "base/basictypes.h" |
91 #include "base/bind.h" | 133 #include "base/bind.h" |
92 #include "base/callback.h" | 134 #include "base/callback.h" |
135 #include "base/memory/scoped_ptr.h" | |
willchan no longer on Chromium
2011/12/07 16:24:34
This isn't necessary is it?
awong
2011/12/08 21:04:10
Not anymore. Removed.
| |
93 #include "base/memory/weak_ptr.h" | 136 #include "base/memory/weak_ptr.h" |
94 #include "base/template_util.h" | 137 #include "base/template_util.h" |
95 | 138 |
96 namespace base { | 139 namespace base { |
97 namespace internal { | 140 namespace internal { |
98 | 141 |
99 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T | 142 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T |
100 // for the existence of AddRef() and Release() functions of the correct | 143 // for the existence of AddRef() and Release() functions of the correct |
101 // signature. | 144 // signature. |
102 // | 145 // |
(...skipping 177 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
280 T* get() const { return ptr_; } | 323 T* get() const { return ptr_; } |
281 OwnedWrapper(const OwnedWrapper& other) { | 324 OwnedWrapper(const OwnedWrapper& other) { |
282 ptr_ = other.ptr_; | 325 ptr_ = other.ptr_; |
283 other.ptr_ = NULL; | 326 other.ptr_ = NULL; |
284 } | 327 } |
285 | 328 |
286 private: | 329 private: |
287 mutable T* ptr_; | 330 mutable T* ptr_; |
288 }; | 331 }; |
289 | 332 |
333 // PassedWrapper is a copyable adapter for a scoper that ignores const. | |
334 // | |
335 // It is needed to get around the fact that Bind() takes a const reference to | |
336 // all its arguments. Because Bind() takes a const reference to avoid | |
337 // unnecessary copies, it is incompatible with moveable-but-not-copyable | |
willchan no longer on Chromium
2011/12/07 16:24:34
s/moveable/movable/
awong
2011/12/08 21:04:10
Done.
| |
338 // types; doing a destructive "move" of the type into Bind() would violate | |
339 // the const correctness. | |
340 // | |
341 // This connundrum cannot be solved without either C++11 rvalue references or | |
342 // a O(2^n) blowup of Bind() templates to handle each combination of regular | |
343 // types and moveable-but-not-copyable types. Thus we introduce a wrapper type | |
willchan no longer on Chromium
2011/12/07 16:24:34
s/moveable/movable/
awong
2011/12/08 21:04:10
Done.
| |
344 // that is copyable to transmit the get the correct type information down into | |
willchan no longer on Chromium
2011/12/07 16:24:34
transmit the get the correct type?
awong
2011/12/08 21:04:10
Done.
| |
345 // BindState<>. Ignoring const in this type makes sense because it is only | |
346 // created when we are explicitly trying to do a destructive move. | |
347 template <typename T> | |
348 class PassedWrapper { | |
349 public: | |
350 explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} | |
willchan no longer on Chromium
2011/12/07 16:24:34
Does this work for anything with Pass() defined? D
awong
2011/12/08 21:04:10
It works for anything with Pass(). I think this i
| |
351 PassedWrapper(const PassedWrapper& other) | |
352 : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { | |
353 } | |
354 T Pass() const { | |
355 CHECK(is_valid_); | |
356 is_valid_ = false; | |
357 return scoper_.Pass(); | |
358 } | |
359 | |
360 private: | |
361 mutable bool is_valid_; | |
362 mutable T scoper_; | |
363 }; | |
364 | |
290 // Unwrap the stored parameters for the wrappers above. | 365 // Unwrap the stored parameters for the wrappers above. |
291 template <typename T> | 366 template <typename T> |
292 struct UnwrapTraits { | 367 struct UnwrapTraits { |
293 typedef const T& ForwardType; | 368 typedef const T& ForwardType; |
294 static ForwardType Unwrap(const T& o) { return o; } | 369 static ForwardType Unwrap(const T& o) { return o; } |
295 }; | 370 }; |
296 | 371 |
297 template <typename T> | 372 template <typename T> |
298 struct UnwrapTraits<UnretainedWrapper<T> > { | 373 struct UnwrapTraits<UnretainedWrapper<T> > { |
299 typedef T* ForwardType; | 374 typedef T* ForwardType; |
(...skipping 23 matching lines...) Expand all Loading... | |
323 }; | 398 }; |
324 | 399 |
325 template <typename T> | 400 template <typename T> |
326 struct UnwrapTraits<OwnedWrapper<T> > { | 401 struct UnwrapTraits<OwnedWrapper<T> > { |
327 typedef T* ForwardType; | 402 typedef T* ForwardType; |
328 static ForwardType Unwrap(const OwnedWrapper<T>& o) { | 403 static ForwardType Unwrap(const OwnedWrapper<T>& o) { |
329 return o.get(); | 404 return o.get(); |
330 } | 405 } |
331 }; | 406 }; |
332 | 407 |
408 template <typename T> | |
409 struct UnwrapTraits<PassedWrapper<T> > { | |
410 typedef T ForwardType; | |
411 static T Unwrap(PassedWrapper<T>& o) { | |
412 return o.Pass(); | |
413 } | |
414 }; | |
415 | |
333 // Utility for handling different refcounting semantics in the Bind() | 416 // Utility for handling different refcounting semantics in the Bind() |
334 // function. | 417 // function. |
335 template <bool, typename T> | 418 template <bool is_method, typename T> |
336 struct MaybeRefcount; | 419 struct MaybeRefcount; |
337 | 420 |
338 template <typename T> | 421 template <typename T> |
339 struct MaybeRefcount<false, T> { | 422 struct MaybeRefcount<false, T> { |
340 static void AddRef(const T&) {} | 423 static void AddRef(const T&) {} |
341 static void Release(const T&) {} | 424 static void Release(const T&) {} |
342 }; | 425 }; |
343 | 426 |
344 template <typename T, size_t n> | 427 template <typename T, size_t n> |
345 struct MaybeRefcount<false, T[n]> { | 428 struct MaybeRefcount<false, T[n]> { |
346 static void AddRef(const T*) {} | 429 static void AddRef(const T*) {} |
347 static void Release(const T*) {} | 430 static void Release(const T*) {} |
348 }; | 431 }; |
349 | 432 |
350 template <typename T> | 433 template <typename T> |
434 struct MaybeRefcount<true, T> { | |
435 static void AddRef(const T&) {} | |
436 static void Release(const T&) {} | |
437 }; | |
438 | |
439 template <typename T> | |
351 struct MaybeRefcount<true, T*> { | 440 struct MaybeRefcount<true, T*> { |
352 static void AddRef(T* o) { o->AddRef(); } | 441 static void AddRef(T* o) { o->AddRef(); } |
353 static void Release(T* o) { o->Release(); } | 442 static void Release(T* o) { o->Release(); } |
354 }; | 443 }; |
355 | 444 |
356 template <typename T> | |
357 struct MaybeRefcount<true, UnretainedWrapper<T> > { | |
358 static void AddRef(const UnretainedWrapper<T>&) {} | |
359 static void Release(const UnretainedWrapper<T>&) {} | |
360 }; | |
361 | |
362 template <typename T> | |
363 struct MaybeRefcount<true, OwnedWrapper<T> > { | |
364 static void AddRef(const OwnedWrapper<T>&) {} | |
365 static void Release(const OwnedWrapper<T>&) {} | |
366 }; | |
367 | |
368 // No need to additionally AddRef() and Release() since we are storing a | 445 // No need to additionally AddRef() and Release() since we are storing a |
369 // scoped_refptr<> inside the storage object already. | 446 // scoped_refptr<> inside the storage object already. |
370 template <typename T> | 447 template <typename T> |
371 struct MaybeRefcount<true, scoped_refptr<T> > { | 448 struct MaybeRefcount<true, scoped_refptr<T> > { |
372 static void AddRef(const scoped_refptr<T>& o) {} | 449 static void AddRef(const scoped_refptr<T>& o) {} |
373 static void Release(const scoped_refptr<T>& o) {} | 450 static void Release(const scoped_refptr<T>& o) {} |
374 }; | 451 }; |
375 | 452 |
376 template <typename T> | 453 template <typename T> |
377 struct MaybeRefcount<true, const T*> { | 454 struct MaybeRefcount<true, const T*> { |
378 static void AddRef(const T* o) { o->AddRef(); } | 455 static void AddRef(const T* o) { o->AddRef(); } |
379 static void Release(const T* o) { o->Release(); } | 456 static void Release(const T* o) { o->Release(); } |
380 }; | 457 }; |
381 | 458 |
382 template <typename T> | |
383 struct MaybeRefcount<true, WeakPtr<T> > { | |
384 static void AddRef(const WeakPtr<T>&) {} | |
385 static void Release(const WeakPtr<T>&) {} | |
386 }; | |
387 | |
388 template <typename R> | 459 template <typename R> |
389 void VoidReturnAdapter(Callback<R(void)> callback) { | 460 void VoidReturnAdapter(Callback<R(void)> callback) { |
390 callback.Run(); | 461 callback.Run(); |
391 } | 462 } |
392 | 463 |
393 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a | 464 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a |
394 // method. It is unsed internally by Bind() to select the correct | 465 // method. It is unsed internally by Bind() to select the correct |
395 // InvokeHelper that will no-op itself in the event the WeakPtr<> for | 466 // InvokeHelper that will no-op itself in the event the WeakPtr<> for |
396 // the target object is invalidated. | 467 // the target object is invalidated. |
397 // | 468 // |
(...skipping 17 matching lines...) Expand all Loading... | |
415 template <typename T> | 486 template <typename T> |
416 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { | 487 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { |
417 return internal::ConstRefWrapper<T>(o); | 488 return internal::ConstRefWrapper<T>(o); |
418 } | 489 } |
419 | 490 |
420 template <typename T> | 491 template <typename T> |
421 static inline internal::OwnedWrapper<T> Owned(T* o) { | 492 static inline internal::OwnedWrapper<T> Owned(T* o) { |
422 return internal::OwnedWrapper<T>(o); | 493 return internal::OwnedWrapper<T>(o); |
423 } | 494 } |
424 | 495 |
496 // We offer 2 syntaxes for calling Passed(). The first takes a temporary and | |
497 // is best suited for use with the return value of a function. The second | |
498 // takes a pointer to the scoper and is just syntactic sugar to avoid having | |
499 // to write Passed(scoper.Pass()). | |
500 template <typename T> | |
501 static inline internal::PassedWrapper<T> Passed(T scoper) { | |
502 return internal::PassedWrapper<T>(scoper.Pass()); | |
503 } | |
504 template <typename T> | |
505 static inline internal::PassedWrapper<T> Passed(T* scoper) { | |
506 return internal::PassedWrapper<T>(scoper->Pass()); | |
507 } | |
508 | |
509 // -- DEPRECATED -- Use IgnoreResult instead. | |
425 template <typename R> | 510 template <typename R> |
426 static inline Closure IgnoreReturn(Callback<R(void)> callback) { | 511 static inline Closure IgnoreReturn(Callback<R(void)> callback) { |
427 return Bind(&internal::VoidReturnAdapter<R>, callback); | 512 return Bind(&internal::VoidReturnAdapter<R>, callback); |
428 } | 513 } |
429 | 514 |
430 template <typename T> | 515 template <typename T> |
431 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { | 516 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { |
432 return internal::IgnoreResultHelper<T>(data); | 517 return internal::IgnoreResultHelper<T>(data); |
433 } | 518 } |
434 | 519 |
435 template <typename T> | 520 template <typename T> |
436 static inline internal::IgnoreResultHelper<Callback<T> > | 521 static inline internal::IgnoreResultHelper<Callback<T> > |
437 IgnoreResult(const Callback<T>& data) { | 522 IgnoreResult(const Callback<T>& data) { |
438 return internal::IgnoreResultHelper<Callback<T> >(data); | 523 return internal::IgnoreResultHelper<Callback<T> >(data); |
439 } | 524 } |
440 | 525 |
441 | |
442 } // namespace base | 526 } // namespace base |
443 | 527 |
444 #endif // BASE_BIND_HELPERS_H_ | 528 #endif // BASE_BIND_HELPERS_H_ |
OLD | NEW |