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

Side by Side Diff: base/bind_helpers.h

Issue 1496403002: base: Stop using Pass() on move-only types in Bind and Callback. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: bind-pass: fixes Created 5 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
« no previous file with comments | « no previous file | base/callback_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 // 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
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
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
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
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 or other temporary
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 T&.
581 template <typename T,
582 typename std::enable_if<internal::IsMoveOnlyType<T>::value &&
583 !std::is_lvalue_reference<T>::value>::type* =
584 nullptr>
585 static inline internal::PassedWrapper<T> Passed(T&& scoper) {
586 return internal::PassedWrapper<T>(std::move(scoper));
576 } 587 }
577 template <typename T> 588 template <typename T,
589 typename std::enable_if<internal::IsMoveOnlyType<T>::value>::type* =
590 nullptr>
578 static inline internal::PassedWrapper<T> Passed(T* scoper) { 591 static inline internal::PassedWrapper<T> Passed(T* scoper) {
579 return internal::PassedWrapper<T>(scoper->Pass()); 592 return internal::PassedWrapper<T>(std::move(*scoper));
580 } 593 }
581 594
582 template <typename T> 595 template <typename T>
583 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) { 596 static inline internal::IgnoreResultHelper<T> IgnoreResult(T data) {
584 return internal::IgnoreResultHelper<T>(data); 597 return internal::IgnoreResultHelper<T>(data);
585 } 598 }
586 599
587 template <typename T> 600 template <typename T>
588 static inline internal::IgnoreResultHelper<Callback<T> > 601 static inline internal::IgnoreResultHelper<Callback<T> >
589 IgnoreResult(const Callback<T>& data) { 602 IgnoreResult(const Callback<T>& data) {
590 return internal::IgnoreResultHelper<Callback<T> >(data); 603 return internal::IgnoreResultHelper<Callback<T> >(data);
591 } 604 }
592 605
593 BASE_EXPORT void DoNothing(); 606 BASE_EXPORT void DoNothing();
594 607
595 template<typename T> 608 template<typename T>
596 void DeletePointer(T* obj) { 609 void DeletePointer(T* obj) {
597 delete obj; 610 delete obj;
598 } 611 }
599 612
600 } // namespace base 613 } // namespace base
601 614
602 #endif // BASE_BIND_HELPERS_H_ 615 #endif // BASE_BIND_HELPERS_H_
OLDNEW
« no previous file with comments | « no previous file | base/callback_internal.h » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698