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

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: Fixed spelling in comments 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') | no next file with comments »
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 transferring movable-but-not-copyable types (eg. scoped_ptr)
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 // transferred ownership to the target function.
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 longer owns Foo() and, if reset, would not delete Foo().
120 // cb.Run(); // Foo() is now transferred to |arg| and deleted.
121 // cb.Run(); // This CHECK()s since Foo() already been used once.
122 //
123 // Passed() is particularly useful with PostTask() when you are transferring
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"
93 #include "base/memory/weak_ptr.h" 135 #include "base/memory/weak_ptr.h"
94 #include "base/template_util.h" 136 #include "base/template_util.h"
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
280 T* get() const { return ptr_; } 322 T* get() const { return ptr_; }
281 OwnedWrapper(const OwnedWrapper& other) { 323 OwnedWrapper(const OwnedWrapper& other) {
282 ptr_ = other.ptr_; 324 ptr_ = other.ptr_;
283 other.ptr_ = NULL; 325 other.ptr_ = NULL;
284 } 326 }
285 327
286 private: 328 private:
287 mutable T* ptr_; 329 mutable T* ptr_;
288 }; 330 };
289 331
332 // PassedWrapper is a copyable adapter for a scoper that ignores const.
333 //
334 // It is needed to get around the fact that Bind() takes a const reference to
335 // all its arguments. Because Bind() takes a const reference to avoid
336 // unnecessary copies, it is incompatible with movable-but-not-copyable
337 // types; doing a destructive "move" of the type into Bind() would violate
338 // the const correctness.
339 //
340 // This conundrum cannot be solved without either C++11 rvalue references or
341 // a O(2^n) blowup of Bind() templates to handle each combination of regular
342 // types and movable-but-not-copyable types. Thus we introduce a wrapper type
343 // that is copyable to transmit the correct type information down into
344 // BindState<>. Ignoring const in this type makes sense because it is only
345 // created when we are explicitly trying to do a destructive move.
346 //
347 // Two notes:
348 // 1) PassedWrapper supports any type that has a "Pass()" function.
349 // This is intentional. The whitelisting of which specific types we
350 // support is maintained by CallbackParamTraits<>.
351 // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL"
352 // scoper to a Callback and allow the Callback to execute once.
353 template <typename T>
354 class PassedWrapper {
355 public:
356 explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {}
357 PassedWrapper(const PassedWrapper& other)
358 : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) {
359 }
360 T Pass() const {
361 CHECK(is_valid_);
362 is_valid_ = false;
363 return scoper_.Pass();
364 }
365
366 private:
367 mutable bool is_valid_;
368 mutable T scoper_;
369 };
370
290 // Unwrap the stored parameters for the wrappers above. 371 // Unwrap the stored parameters for the wrappers above.
291 template <typename T> 372 template <typename T>
292 struct UnwrapTraits { 373 struct UnwrapTraits {
293 typedef const T& ForwardType; 374 typedef const T& ForwardType;
294 static ForwardType Unwrap(const T& o) { return o; } 375 static ForwardType Unwrap(const T& o) { return o; }
295 }; 376 };
296 377
297 template <typename T> 378 template <typename T>
298 struct UnwrapTraits<UnretainedWrapper<T> > { 379 struct UnwrapTraits<UnretainedWrapper<T> > {
299 typedef T* ForwardType; 380 typedef T* ForwardType;
(...skipping 23 matching lines...) Expand all
323 }; 404 };
324 405
325 template <typename T> 406 template <typename T>
326 struct UnwrapTraits<OwnedWrapper<T> > { 407 struct UnwrapTraits<OwnedWrapper<T> > {
327 typedef T* ForwardType; 408 typedef T* ForwardType;
328 static ForwardType Unwrap(const OwnedWrapper<T>& o) { 409 static ForwardType Unwrap(const OwnedWrapper<T>& o) {
329 return o.get(); 410 return o.get();
330 } 411 }
331 }; 412 };
332 413
414 template <typename T>
415 struct UnwrapTraits<PassedWrapper<T> > {
416 typedef T ForwardType;
417 static T Unwrap(PassedWrapper<T>& o) {
418 return o.Pass();
419 }
420 };
421
333 // Utility for handling different refcounting semantics in the Bind() 422 // Utility for handling different refcounting semantics in the Bind()
334 // function. 423 // function.
335 template <bool, typename T> 424 template <bool is_method, typename T>
336 struct MaybeRefcount; 425 struct MaybeRefcount;
337 426
338 template <typename T> 427 template <typename T>
339 struct MaybeRefcount<false, T> { 428 struct MaybeRefcount<false, T> {
340 static void AddRef(const T&) {} 429 static void AddRef(const T&) {}
341 static void Release(const T&) {} 430 static void Release(const T&) {}
342 }; 431 };
343 432
344 template <typename T, size_t n> 433 template <typename T, size_t n>
345 struct MaybeRefcount<false, T[n]> { 434 struct MaybeRefcount<false, T[n]> {
346 static void AddRef(const T*) {} 435 static void AddRef(const T*) {}
347 static void Release(const T*) {} 436 static void Release(const T*) {}
348 }; 437 };
349 438
350 template <typename T> 439 template <typename T>
440 struct MaybeRefcount<true, T> {
441 static void AddRef(const T&) {}
442 static void Release(const T&) {}
443 };
444
445 template <typename T>
351 struct MaybeRefcount<true, T*> { 446 struct MaybeRefcount<true, T*> {
352 static void AddRef(T* o) { o->AddRef(); } 447 static void AddRef(T* o) { o->AddRef(); }
353 static void Release(T* o) { o->Release(); } 448 static void Release(T* o) { o->Release(); }
354 }; 449 };
355 450
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 451 // No need to additionally AddRef() and Release() since we are storing a
369 // scoped_refptr<> inside the storage object already. 452 // scoped_refptr<> inside the storage object already.
370 template <typename T> 453 template <typename T>
371 struct MaybeRefcount<true, scoped_refptr<T> > { 454 struct MaybeRefcount<true, scoped_refptr<T> > {
372 static void AddRef(const scoped_refptr<T>& o) {} 455 static void AddRef(const scoped_refptr<T>& o) {}
373 static void Release(const scoped_refptr<T>& o) {} 456 static void Release(const scoped_refptr<T>& o) {}
374 }; 457 };
375 458
376 template <typename T> 459 template <typename T>
377 struct MaybeRefcount<true, const T*> { 460 struct MaybeRefcount<true, const T*> {
378 static void AddRef(const T* o) { o->AddRef(); } 461 static void AddRef(const T* o) { o->AddRef(); }
379 static void Release(const T* o) { o->Release(); } 462 static void Release(const T* o) { o->Release(); }
380 }; 463 };
381 464
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> 465 template <typename R>
389 void VoidReturnAdapter(Callback<R(void)> callback) { 466 void VoidReturnAdapter(Callback<R(void)> callback) {
390 callback.Run(); 467 callback.Run();
391 } 468 }
392 469
393 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a 470 // 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 471 // method. It is used internally by Bind() to select the correct
395 // InvokeHelper that will no-op itself in the event the WeakPtr<> for 472 // InvokeHelper that will no-op itself in the event the WeakPtr<> for
396 // the target object is invalidated. 473 // the target object is invalidated.
397 // 474 //
398 // P1 should be the type of the object that will be received of the method. 475 // P1 should be the type of the object that will be received of the method.
399 template <bool IsMethod, typename P1> 476 template <bool IsMethod, typename P1>
400 struct IsWeakMethod : public false_type {}; 477 struct IsWeakMethod : public false_type {};
401 478
402 template <typename T> 479 template <typename T>
403 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; 480 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
404 481
(...skipping 10 matching lines...) Expand all
415 template <typename T> 492 template <typename T>
416 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { 493 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
417 return internal::ConstRefWrapper<T>(o); 494 return internal::ConstRefWrapper<T>(o);
418 } 495 }
419 496
420 template <typename T> 497 template <typename T>
421 static inline internal::OwnedWrapper<T> Owned(T* o) { 498 static inline internal::OwnedWrapper<T> Owned(T* o) {
422 return internal::OwnedWrapper<T>(o); 499 return internal::OwnedWrapper<T>(o);
423 } 500 }
424 501
502 // We offer 2 syntaxes for calling Passed(). The first takes a temporary and
503 // is best suited for use with the return value of a function. The second
504 // takes a pointer to the scoper and is just syntactic sugar to avoid having
505 // to write Passed(scoper.Pass()).
506 template <typename T>
507 static inline internal::PassedWrapper<T> Passed(T scoper) {
508 return internal::PassedWrapper<T>(scoper.Pass());
509 }
510 template <typename T>
511 static inline internal::PassedWrapper<T> Passed(T* scoper) {
512 return internal::PassedWrapper<T>(scoper->Pass());
513 }
514
515 // -- DEPRECATED -- Use IgnoreResult instead.
425 template <typename R> 516 template <typename R>
426 static inline Closure IgnoreReturn(Callback<R(void)> callback) { 517 static inline Closure IgnoreReturn(Callback<R(void)> callback) {
427 return Bind(&internal::VoidReturnAdapter<R>, callback); 518 return Bind(&internal::VoidReturnAdapter<R>, callback);
428 } 519 }
429 520
430 template <typename T> 521 template <typename T>
431 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { 522 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
432 return internal::IgnoreResultHelper<T>(data); 523 return internal::IgnoreResultHelper<T>(data);
433 } 524 }
434 525
435 template <typename T> 526 template <typename T>
436 static inline internal::IgnoreResultHelper<Callback<T> > 527 static inline internal::IgnoreResultHelper<Callback<T> >
437 IgnoreResult(const Callback<T>& data) { 528 IgnoreResult(const Callback<T>& data) {
438 return internal::IgnoreResultHelper<Callback<T> >(data); 529 return internal::IgnoreResultHelper<Callback<T> >(data);
439 } 530 }
440 531
441
442 } // namespace base 532 } // namespace base
443 533
444 #endif // BASE_BIND_HELPERS_H_ 534 #endif // BASE_BIND_HELPERS_H_
OLDNEW
« no previous file with comments | « no previous file | base/bind_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698