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

Side by Side Diff: base/bind_helpers.h

Issue 8774032: Add Pass(), which implements move semantics, to scoped_ptr, scoped_array, and scoped_ptr_malloc. (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src
Patch Set: Fix comments, make Passed() support temporaries, fix unbound argument forwarding, add more tests. Created 9 years 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 | Annotate | Revision Log
« no previous file with comments | « no previous file | base/bind_internal.h » ('j') | base/callback_internal.h » ('J')
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
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
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
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
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
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_
OLDNEW
« no previous file with comments | « no previous file | base/bind_internal.h » ('j') | base/callback_internal.h » ('J')

Powered by Google App Engine
This is Rietveld 408576698