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 // It also defines a set of simple functions and utilities that people want | 9 // It also defines a set of simple functions and utilities that people want |
10 // when using Callback<> and Bind(). | 10 // when using Callback<> and Bind(). |
(...skipping 93 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
104 // | 104 // |
105 // | 105 // |
106 // EXAMPLE OF Passed(): | 106 // EXAMPLE OF Passed(): |
107 // | 107 // |
108 // void TakesOwnership(scoped_ptr<Foo> arg) { } | 108 // void TakesOwnership(scoped_ptr<Foo> arg) { } |
109 // scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } | 109 // scoped_ptr<Foo> CreateFoo() { return scoped_ptr<Foo>(new Foo()); } |
110 // | 110 // |
111 // scoped_ptr<Foo> f(new Foo()); | 111 // scoped_ptr<Foo> f(new Foo()); |
112 // | 112 // |
113 // // |cb| is given ownership of Foo(). |f| is now NULL. | 113 // // |cb| is given ownership of Foo(). |f| is now NULL. |
114 // // You can use f.Pass() in place of &f, but it's more verbose. | 114 // // You can use std::move(f) in place of &f, but it's more verbose. |
115 // Closure cb = Bind(&TakesOwnership, Passed(&f)); | 115 // Closure cb = Bind(&TakesOwnership, Passed(&f)); |
116 // | 116 // |
117 // // Run was never called so |cb| still owns Foo() and deletes | 117 // // Run was never called so |cb| still owns Foo() and deletes |
118 // // it on Reset(). | 118 // // it on Reset(). |
119 // cb.Reset(); | 119 // cb.Reset(); |
120 // | 120 // |
121 // // |cb| is given a new Foo created by CreateFoo(). | 121 // // |cb| is given a new Foo created by CreateFoo(). |
122 // cb = Bind(&TakesOwnership, Passed(CreateFoo())); | 122 // cb = Bind(&TakesOwnership, Passed(CreateFoo())); |
123 // | 123 // |
124 // // |arg| in TakesOwnership() is given ownership of Foo(). |cb| | 124 // // |arg| in TakesOwnership() is given ownership of Foo(). |cb| |
(...skipping 11 matching lines...) Expand all Loading... | |
136 // | 136 // |
137 // DoNothing() - Useful for creating a Closure that does nothing when called. | 137 // DoNothing() - Useful for creating a Closure that does nothing when called. |
138 // DeletePointer<T>() - Useful for creating a Closure that will delete a | 138 // DeletePointer<T>() - Useful for creating a Closure that will delete a |
139 // pointer when invoked. Only use this when necessary. | 139 // pointer when invoked. Only use this when necessary. |
140 // In most cases MessageLoop::DeleteSoon() is a better | 140 // In most cases MessageLoop::DeleteSoon() is a better |
141 // fit. | 141 // fit. |
142 | 142 |
143 #ifndef BASE_BIND_HELPERS_H_ | 143 #ifndef BASE_BIND_HELPERS_H_ |
144 #define BASE_BIND_HELPERS_H_ | 144 #define BASE_BIND_HELPERS_H_ |
145 | 145 |
146 #include <type_traits> | |
147 #include <utility> | |
148 | |
146 #include "base/basictypes.h" | 149 #include "base/basictypes.h" |
147 #include "base/callback.h" | 150 #include "base/callback.h" |
148 #include "base/memory/weak_ptr.h" | 151 #include "base/memory/weak_ptr.h" |
149 #include "base/template_util.h" | 152 #include "base/template_util.h" |
150 | 153 |
151 namespace base { | 154 namespace base { |
152 namespace internal { | 155 namespace internal { |
153 | 156 |
154 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T | 157 // Use the Substitution Failure Is Not An Error (SFINAE) trick to inspect T |
155 // for the existence of AddRef() and Release() functions of the correct | 158 // for the existence of AddRef() and Release() functions of the correct |
(...skipping 196 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
352 // the const correctness. | 355 // the const correctness. |
353 // | 356 // |
354 // This conundrum cannot be solved without either C++11 rvalue references or | 357 // This conundrum cannot be solved without either C++11 rvalue references or |
355 // a O(2^n) blowup of Bind() templates to handle each combination of regular | 358 // a O(2^n) blowup of Bind() templates to handle each combination of regular |
356 // types and movable-but-not-copyable types. Thus we introduce a wrapper type | 359 // types and movable-but-not-copyable types. Thus we introduce a wrapper type |
357 // that is copyable to transmit the correct type information down into | 360 // that is copyable to transmit the correct type information down into |
358 // BindState<>. Ignoring const in this type makes sense because it is only | 361 // BindState<>. Ignoring const in this type makes sense because it is only |
359 // created when we are explicitly trying to do a destructive move. | 362 // created when we are explicitly trying to do a destructive move. |
360 // | 363 // |
361 // Two notes: | 364 // Two notes: |
362 // 1) PassedWrapper supports any type that has a "Pass()" function. | 365 // 1) PassedWrapper supports any type that has a move constructor, however |
363 // This is intentional. The whitelisting of which specific types we | 366 // the type will need to be specifically whitelisted in order for it to be |
364 // support is maintained by CallbackParamTraits<>. | 367 // bound to a Callback. We guard this explicitly at the call of Passed() |
368 // to make for clear errors. Things not given to Passed() will be forwarded | |
369 // and stored by value which will not work for general move-only types. | |
365 // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" | 370 // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" |
366 // scoper to a Callback and allow the Callback to execute once. | 371 // scoper to a Callback and allow the Callback to execute once. |
367 template <typename T> | 372 template <typename T> |
368 class PassedWrapper { | 373 class PassedWrapper { |
369 public: | 374 public: |
370 explicit PassedWrapper(T scoper) : is_valid_(true), scoper_(scoper.Pass()) {} | 375 explicit PassedWrapper(T&& scoper) |
376 : is_valid_(true), scoper_(std::move(scoper)) {} | |
371 PassedWrapper(const PassedWrapper& other) | 377 PassedWrapper(const PassedWrapper& other) |
372 : is_valid_(other.is_valid_), scoper_(other.scoper_.Pass()) { | 378 : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} |
373 } | |
374 T Pass() const { | 379 T Pass() const { |
375 CHECK(is_valid_); | 380 CHECK(is_valid_); |
376 is_valid_ = false; | 381 is_valid_ = false; |
377 return scoper_.Pass(); | 382 return std::move(scoper_); |
378 } | 383 } |
379 | 384 |
380 private: | 385 private: |
381 mutable bool is_valid_; | 386 mutable bool is_valid_; |
382 mutable T scoper_; | 387 mutable T scoper_; |
383 }; | 388 }; |
384 | 389 |
385 // Unwrap the stored parameters for the wrappers above. | 390 // Unwrap the stored parameters for the wrappers above. |
386 template <typename T> | 391 template <typename T> |
387 struct UnwrapTraits { | 392 struct UnwrapTraits { |
(...skipping 171 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
559 template <typename T> | 564 template <typename T> |
560 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { | 565 static inline internal::ConstRefWrapper<T> ConstRef(const T& o) { |
561 return internal::ConstRefWrapper<T>(o); | 566 return internal::ConstRefWrapper<T>(o); |
562 } | 567 } |
563 | 568 |
564 template <typename T> | 569 template <typename T> |
565 static inline internal::OwnedWrapper<T> Owned(T* o) { | 570 static inline internal::OwnedWrapper<T> Owned(T* o) { |
566 return internal::OwnedWrapper<T>(o); | 571 return internal::OwnedWrapper<T>(o); |
567 } | 572 } |
568 | 573 |
569 // We offer 2 syntaxes for calling Passed(). The first takes a temporary and | 574 // We offer 2 syntaxes for calling Passed(). The first takes an rvalue and |
570 // is best suited for use with the return value of a function. The second | 575 // is best suited for use with the return value of a function of other temporary |
Nico
2015/12/04 22:08:16
s/of other/or other/
danakj
2015/12/04 22:09:30
Done.
| |
571 // takes a pointer to the scoper and is just syntactic sugar to avoid having | 576 // rvalues. The second takes a pointer to the scoper and is just syntactic sugar |
572 // to write Passed(scoper.Pass()). | 577 // to avoid having to write Passed(std::move(scoper)). |
573 template <typename T> | 578 // |
574 static inline internal::PassedWrapper<T> Passed(T scoper) { | 579 // Both versions of Passed() prevent T from being an lvalue reference. The first |
575 return internal::PassedWrapper<T>(scoper.Pass()); | 580 // via use of enable_if, and the second takes a T* which will not bind to a T |
dcheng
2015/12/04 22:07:08
Nit. I think you can just say T* which will not bi
danakj
2015/12/04 22:09:30
Done.
| |
581 // that is a reference. | |
582 template <typename T, | |
583 typename std::enable_if<internal::IsMoveOnlyType<T>::value && | |
584 !std::is_lvalue_reference<T>::value>::type* = | |
585 nullptr> | |
586 static inline internal::PassedWrapper<T> Passed(T&& scoper) { | |
587 return internal::PassedWrapper<T>(std::move(scoper)); | |
576 } | 588 } |
577 template <typename T> | 589 template <typename T, |
590 typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* = | |
591 nullptr> | |
578 static inline internal::PassedWrapper<T> Passed(T* scoper) { | 592 static inline internal::PassedWrapper<T> Passed(T* scoper) { |
579 return internal::PassedWrapper<T>(scoper->Pass()); | 593 return internal::PassedWrapper<T>(std::move(*scoper)); |
580 } | 594 } |
581 | 595 |
582 template <typename T> | 596 template <typename T> |
583 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { | 597 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { |
584 return internal::IgnoreResultHelper<T>(data); | 598 return internal::IgnoreResultHelper<T>(data); |
585 } | 599 } |
586 | 600 |
587 template <typename T> | 601 template <typename T> |
588 static inline internal::IgnoreResultHelper<Callback<T> > | 602 static inline internal::IgnoreResultHelper<Callback<T> > |
589 IgnoreResult(const Callback<T>& data) { | 603 IgnoreResult(const Callback<T>& data) { |
590 return internal::IgnoreResultHelper<Callback<T> >(data); | 604 return internal::IgnoreResultHelper<Callback<T> >(data); |
591 } | 605 } |
592 | 606 |
593 BASE_EXPORT void DoNothing(); | 607 BASE_EXPORT void DoNothing(); |
594 | 608 |
595 template<typename T> | 609 template<typename T> |
596 void DeletePointer(T* obj) { | 610 void DeletePointer(T* obj) { |
597 delete obj; | 611 delete obj; |
598 } | 612 } |
599 | 613 |
600 } // namespace base | 614 } // namespace base |
601 | 615 |
602 #endif // BASE_BIND_HELPERS_H_ | 616 #endif // BASE_BIND_HELPERS_H_ |
OLD | NEW |