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

Side by Side Diff: base/bind_helpers.h

Issue 8949057: Revert 115441 - Redo r113722 - Add Pass(), which implements move semantics, to scoped_ptr, scoped... (Closed) Base URL: svn://svn.chromium.org/chrome/trunk/src/
Patch Set: 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(), bass::Passed(), 9 // The public functions are base::Unretained(), base::Owned(),
10 // base::ConstRef(), and base::IgnoreResult(). 10 // base::ConstRef(), and base::IgnoreReturn().
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 //
15 // Owned() transfers ownership of an object to the Callback resulting from 14 // Owned() transfers ownership of an object to the Callback resulting from
16 // bind; the object will be deleted when the Callback is deleted. 15 // 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 //
25 // ConstRef() allows binding a constant reference to an argument rather 16 // ConstRef() allows binding a constant reference to an argument rather
26 // than a copy. 17 // 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.
27 // 21 //
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.
32 // 22 //
33 // EXAMPLE OF Unretained(): 23 // EXAMPLE OF Unretained():
34 // 24 //
35 // class Foo { 25 // class Foo {
36 // public: 26 // public:
37 // void func() { cout << "Foo:f" << endl; } 27 // void func() { cout << "Foo:f" << endl; }
38 // }; 28 // };
39 // 29 //
40 // // In some function somewhere. 30 // // In some function somewhere.
41 // Foo foo; 31 // Foo foo;
(...skipping 36 matching lines...) Expand 10 before | Expand all | Expand 10 after
78 // has_ref.Run(); // Prints "1" 68 // has_ref.Run(); // Prints "1"
79 // 69 //
80 // n = 2; 70 // n = 2;
81 // no_ref.Run(); // Prints "1" 71 // no_ref.Run(); // Prints "1"
82 // has_ref.Run(); // Prints "2" 72 // has_ref.Run(); // Prints "2"
83 // 73 //
84 // 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
85 // its bound callbacks. 75 // its bound callbacks.
86 // 76 //
87 // 77 //
88 // EXAMPLE OF IgnoreResult(): 78 // EXAMPLE OF IgnoreReturn():
89 // 79 //
90 // int DoSomething(int arg) { cout << arg << endl; } 80 // int DoSomething(int arg) { cout << arg << endl; }
91 // 81 // Callback<int(void)> cb = Bind(&DoSomething, 1);
92 // // Assign to a Callback with a void return type. 82 // Closure c = IgnoreReturn(cb); // Prints "1"
93 // Callback<void(int)> cb = Bind(IgnoreResult(&DoSomething)); 83 // or
94 // cb->Run(1); // Prints "1". 84 // ml->PostTask(FROM_HERE, IgnoreReturn(cb)); // Prints "1" on |ml|
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.
127 85
128 #ifndef BASE_BIND_HELPERS_H_ 86 #ifndef BASE_BIND_HELPERS_H_
129 #define BASE_BIND_HELPERS_H_ 87 #define BASE_BIND_HELPERS_H_
130 #pragma once 88 #pragma once
131 89
132 #include "base/basictypes.h" 90 #include "base/basictypes.h"
133 #include "base/bind.h" 91 #include "base/bind.h"
134 #include "base/callback.h" 92 #include "base/callback.h"
135 #include "base/memory/weak_ptr.h" 93 #include "base/memory/weak_ptr.h"
136 #include "base/template_util.h" 94 #include "base/template_util.h"
(...skipping 185 matching lines...) Expand 10 before | Expand all | Expand 10 after
322 T* get() const { return ptr_; } 280 T* get() const { return ptr_; }
323 OwnedWrapper(const OwnedWrapper& other) { 281 OwnedWrapper(const OwnedWrapper& other) {
324 ptr_ = other.ptr_; 282 ptr_ = other.ptr_;
325 other.ptr_ = NULL; 283 other.ptr_ = NULL;
326 } 284 }
327 285
328 private: 286 private:
329 mutable T* ptr_; 287 mutable T* ptr_;
330 }; 288 };
331 289
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
371 // Unwrap the stored parameters for the wrappers above. 290 // Unwrap the stored parameters for the wrappers above.
372 template <typename T> 291 template <typename T>
373 struct UnwrapTraits { 292 struct UnwrapTraits {
374 typedef const T& ForwardType; 293 typedef const T& ForwardType;
375 static ForwardType Unwrap(const T& o) { return o; } 294 static ForwardType Unwrap(const T& o) { return o; }
376 }; 295 };
377 296
378 template <typename T> 297 template <typename T>
379 struct UnwrapTraits<UnretainedWrapper<T> > { 298 struct UnwrapTraits<UnretainedWrapper<T> > {
380 typedef T* ForwardType; 299 typedef T* ForwardType;
(...skipping 23 matching lines...) Expand all
404 }; 323 };
405 324
406 template <typename T> 325 template <typename T>
407 struct UnwrapTraits<OwnedWrapper<T> > { 326 struct UnwrapTraits<OwnedWrapper<T> > {
408 typedef T* ForwardType; 327 typedef T* ForwardType;
409 static ForwardType Unwrap(const OwnedWrapper<T>& o) { 328 static ForwardType Unwrap(const OwnedWrapper<T>& o) {
410 return o.get(); 329 return o.get();
411 } 330 }
412 }; 331 };
413 332
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
422 // Utility for handling different refcounting semantics in the Bind() 333 // Utility for handling different refcounting semantics in the Bind()
423 // function. 334 // function.
424 template <bool is_method, typename T> 335 template <bool, typename T>
425 struct MaybeRefcount; 336 struct MaybeRefcount;
426 337
427 template <typename T> 338 template <typename T>
428 struct MaybeRefcount<false, T> { 339 struct MaybeRefcount<false, T> {
429 static void AddRef(const T&) {} 340 static void AddRef(const T&) {}
430 static void Release(const T&) {} 341 static void Release(const T&) {}
431 }; 342 };
432 343
433 template <typename T, size_t n> 344 template <typename T, size_t n>
434 struct MaybeRefcount<false, T[n]> { 345 struct MaybeRefcount<false, T[n]> {
435 static void AddRef(const T*) {} 346 static void AddRef(const T*) {}
436 static void Release(const T*) {} 347 static void Release(const T*) {}
437 }; 348 };
438 349
439 template <typename T> 350 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>
446 struct MaybeRefcount<true, T*> { 351 struct MaybeRefcount<true, T*> {
447 static void AddRef(T* o) { o->AddRef(); } 352 static void AddRef(T* o) { o->AddRef(); }
448 static void Release(T* o) { o->Release(); } 353 static void Release(T* o) { o->Release(); }
449 }; 354 };
450 355
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
451 // No need to additionally AddRef() and Release() since we are storing a 368 // No need to additionally AddRef() and Release() since we are storing a
452 // scoped_refptr<> inside the storage object already. 369 // scoped_refptr<> inside the storage object already.
453 template <typename T> 370 template <typename T>
454 struct MaybeRefcount<true, scoped_refptr<T> > { 371 struct MaybeRefcount<true, scoped_refptr<T> > {
455 static void AddRef(const scoped_refptr<T>& o) {} 372 static void AddRef(const scoped_refptr<T>& o) {}
456 static void Release(const scoped_refptr<T>& o) {} 373 static void Release(const scoped_refptr<T>& o) {}
457 }; 374 };
458 375
459 template <typename T> 376 template <typename T>
460 struct MaybeRefcount<true, const T*> { 377 struct MaybeRefcount<true, const T*> {
461 static void AddRef(const T* o) { o->AddRef(); } 378 static void AddRef(const T* o) { o->AddRef(); }
462 static void Release(const T* o) { o->Release(); } 379 static void Release(const T* o) { o->Release(); }
463 }; 380 };
464 381
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
465 template <typename R> 388 template <typename R>
466 void VoidReturnAdapter(Callback<R(void)> callback) { 389 void VoidReturnAdapter(Callback<R(void)> callback) {
467 callback.Run(); 390 callback.Run();
468 } 391 }
469 392
470 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a 393 // IsWeakMethod is a helper that determine if we are binding a WeakPtr<> to a
471 // method. It is used internally by Bind() to select the correct 394 // method. It is unsed internally by Bind() to select the correct
472 // InvokeHelper that will no-op itself in the event the WeakPtr<> for 395 // InvokeHelper that will no-op itself in the event the WeakPtr<> for
473 // the target object is invalidated. 396 // the target object is invalidated.
474 // 397 //
475 // P1 should be the type of the object that will be received of the method. 398 // P1 should be the type of the object that will be received of the method.
476 template <bool IsMethod, typename P1> 399 template <bool IsMethod, typename P1>
477 struct IsWeakMethod : public false_type {}; 400 struct IsWeakMethod : public false_type {};
478 401
479 template <typename T> 402 template <typename T>
480 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {}; 403 struct IsWeakMethod<true, WeakPtr<T> > : public true_type {};
481 404
(...skipping 10 matching lines...) Expand all
492 template <typename T> 415 template <typename T>
493 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { 416 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) {
494 return internal::ConstRefWrapper<T>(o); 417 return internal::ConstRefWrapper<T>(o);
495 } 418 }
496 419
497 template <typename T> 420 template <typename T>
498 static inline internal::OwnedWrapper<T> Owned(T* o) { 421 static inline internal::OwnedWrapper<T> Owned(T* o) {
499 return internal::OwnedWrapper<T>(o); 422 return internal::OwnedWrapper<T>(o);
500 } 423 }
501 424
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.
516 template <typename R> 425 template <typename R>
517 static inline Closure IgnoreReturn(Callback<R(void)> callback) { 426 static inline Closure IgnoreReturn(Callback<R(void)> callback) {
518 return Bind(&internal::VoidReturnAdapter<R>, callback); 427 return Bind(&internal::VoidReturnAdapter<R>, callback);
519 } 428 }
520 429
521 template <typename T> 430 template <typename T>
522 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { 431 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
523 return internal::IgnoreResultHelper<T>(data); 432 return internal::IgnoreResultHelper<T>(data);
524 } 433 }
525 434
526 template <typename T> 435 template <typename T>
527 static inline internal::IgnoreResultHelper<Callback<T> > 436 static inline internal::IgnoreResultHelper<Callback<T> >
528 IgnoreResult(const Callback<T>& data) { 437 IgnoreResult(const Callback<T>& data) {
529 return internal::IgnoreResultHelper<Callback<T> >(data); 438 return internal::IgnoreResultHelper<Callback<T> >(data);
530 } 439 }
531 440
441
532 } // namespace base 442 } // namespace base
533 443
534 #endif // BASE_BIND_HELPERS_H_ 444 #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