Chromium Code Reviews| 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 338 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 349 }; | 349 }; |
| 350 | 350 |
| 351 // PassedWrapper is a copyable adapter for a scoper that ignores const. | 351 // PassedWrapper is a copyable adapter for a scoper that ignores const. |
| 352 // | 352 // |
| 353 // It is needed to get around the fact that Bind() takes a const reference to | 353 // It is needed to get around the fact that Bind() takes a const reference to |
| 354 // all its arguments. Because Bind() takes a const reference to avoid | 354 // all its arguments. Because Bind() takes a const reference to avoid |
| 355 // unnecessary copies, it is incompatible with movable-but-not-copyable | 355 // unnecessary copies, it is incompatible with movable-but-not-copyable |
| 356 // types; doing a destructive "move" of the type into Bind() would violate | 356 // types; doing a destructive "move" of the type into Bind() would violate |
| 357 // the const correctness. | 357 // the const correctness. |
| 358 // | 358 // |
| 359 // This conundrum cannot be solved without either C++11 rvalue references or | 359 // This conundrum cannot be solved without either C++11 rvalue references or |
|
Nico
2016/02/16 14:57:10
do we still need this type?
tzik
2016/02/16 15:22:17
Yes, we still need this for a while for Run() impl
Nico
2016/02/16 15:24:22
Maybe the comment could use updating then :-)
| |
| 360 // a O(2^n) blowup of Bind() templates to handle each combination of regular | 360 // a O(2^n) blowup of Bind() templates to handle each combination of regular |
| 361 // types and movable-but-not-copyable types. Thus we introduce a wrapper type | 361 // types and movable-but-not-copyable types. Thus we introduce a wrapper type |
| 362 // that is copyable to transmit the correct type information down into | 362 // that is copyable to transmit the correct type information down into |
| 363 // BindState<>. Ignoring const in this type makes sense because it is only | 363 // BindState<>. Ignoring const in this type makes sense because it is only |
| 364 // created when we are explicitly trying to do a destructive move. | 364 // created when we are explicitly trying to do a destructive move. |
| 365 // | 365 // |
| 366 // Two notes: | 366 // Two notes: |
| 367 // 1) PassedWrapper supports any type that has a move constructor, however | 367 // 1) PassedWrapper supports any type that has a move constructor, however |
| 368 // the type will need to be specifically whitelisted in order for it to be | 368 // the type will need to be specifically whitelisted in order for it to be |
| 369 // bound to a Callback. We guard this explicitly at the call of Passed() | 369 // bound to a Callback. We guard this explicitly at the call of Passed() |
| 370 // to make for clear errors. Things not given to Passed() will be forwarded | 370 // to make for clear errors. Things not given to Passed() will be forwarded |
| 371 // and stored by value which will not work for general move-only types. | 371 // and stored by value which will not work for general move-only types. |
| 372 // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" | 372 // 2) is_valid_ is distinct from NULL because it is valid to bind a "NULL" |
| 373 // scoper to a Callback and allow the Callback to execute once. | 373 // scoper to a Callback and allow the Callback to execute once. |
| 374 template <typename T> | 374 template <typename T> |
| 375 class PassedWrapper { | 375 class PassedWrapper { |
| 376 public: | 376 public: |
| 377 explicit PassedWrapper(T&& scoper) | 377 explicit PassedWrapper(T&& scoper) |
| 378 : is_valid_(true), scoper_(std::move(scoper)) {} | 378 : is_valid_(true), scoper_(std::move(scoper)) {} |
| 379 PassedWrapper(const PassedWrapper& other) | 379 PassedWrapper(const PassedWrapper& other) |
| 380 : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} | 380 : is_valid_(other.is_valid_), scoper_(std::move(other.scoper_)) {} |
| 381 T Pass() const { | 381 T Take() const { |
| 382 CHECK(is_valid_); | 382 CHECK(is_valid_); |
| 383 is_valid_ = false; | 383 is_valid_ = false; |
| 384 return std::move(scoper_); | 384 return std::move(scoper_); |
| 385 } | 385 } |
| 386 | 386 |
| 387 private: | 387 private: |
| 388 mutable bool is_valid_; | 388 mutable bool is_valid_; |
| 389 mutable T scoper_; | 389 mutable T scoper_; |
| 390 }; | 390 }; |
| 391 | 391 |
| 392 // Unwrap the stored parameters for the wrappers above. | 392 // Unwrap the stored parameters for the wrappers above. |
| 393 template <typename T> | 393 template <typename T> |
| 394 struct UnwrapTraits { | 394 const T& Unwrap(const T& o) { |
| 395 using ForwardType = const T&; | 395 return o; |
| 396 static ForwardType Unwrap(const T& o) { return o; } | 396 } |
| 397 }; | |
| 398 | 397 |
| 399 template <typename T> | 398 template <typename T> |
| 400 struct UnwrapTraits<UnretainedWrapper<T> > { | 399 T* Unwrap(UnretainedWrapper<T> unretained) { |
| 401 using ForwardType = T*; | 400 return unretained.get(); |
| 402 static ForwardType Unwrap(UnretainedWrapper<T> unretained) { | 401 } |
| 403 return unretained.get(); | |
| 404 } | |
| 405 }; | |
| 406 | 402 |
| 407 template <typename T> | 403 template <typename T> |
| 408 struct UnwrapTraits<ConstRefWrapper<T> > { | 404 const T& Unwrap(ConstRefWrapper<T> const_ref) { |
| 409 using ForwardType = const T&; | 405 return const_ref.get(); |
| 410 static ForwardType Unwrap(ConstRefWrapper<T> const_ref) { | 406 } |
| 411 return const_ref.get(); | |
| 412 } | |
| 413 }; | |
| 414 | 407 |
| 415 template <typename T> | 408 template <typename T> |
| 416 struct UnwrapTraits<scoped_refptr<T> > { | 409 T* Unwrap(const scoped_refptr<T>& o) { |
| 417 using ForwardType = T*; | 410 return o.get(); |
| 418 static ForwardType Unwrap(const scoped_refptr<T>& o) { return o.get(); } | 411 } |
| 419 }; | |
| 420 | 412 |
| 421 template <typename T> | 413 template <typename T> |
| 422 struct UnwrapTraits<WeakPtr<T> > { | 414 const WeakPtr<T>& Unwrap(const WeakPtr<T>& o) { |
| 423 using ForwardType = const WeakPtr<T>&; | 415 return o; |
| 424 static ForwardType Unwrap(const WeakPtr<T>& o) { return o; } | 416 } |
| 425 }; | |
| 426 | 417 |
| 427 template <typename T> | 418 template <typename T> |
| 428 struct UnwrapTraits<OwnedWrapper<T> > { | 419 T* Unwrap(const OwnedWrapper<T>& o) { |
| 429 using ForwardType = T*; | 420 return o.get(); |
| 430 static ForwardType Unwrap(const OwnedWrapper<T>& o) { | 421 } |
| 431 return o.get(); | |
| 432 } | |
| 433 }; | |
| 434 | 422 |
| 435 template <typename T> | 423 template <typename T> |
| 436 struct UnwrapTraits<PassedWrapper<T> > { | 424 T Unwrap(PassedWrapper<T>& o) { |
| 437 using ForwardType = T; | 425 return o.Take(); |
| 438 static T Unwrap(PassedWrapper<T>& o) { | 426 } |
| 439 return o.Pass(); | |
| 440 } | |
| 441 }; | |
| 442 | 427 |
| 443 // Utility for handling different refcounting semantics in the Bind() | 428 // Utility for handling different refcounting semantics in the Bind() |
| 444 // function. | 429 // function. |
| 445 template <bool is_method, typename... T> | 430 template <bool is_method, typename... T> |
| 446 struct MaybeScopedRefPtr; | 431 struct MaybeScopedRefPtr; |
| 447 | 432 |
| 448 template <bool is_method> | 433 template <bool is_method> |
| 449 struct MaybeScopedRefPtr<is_method> { | 434 struct MaybeScopedRefPtr<is_method> { |
| 450 MaybeScopedRefPtr() {} | 435 MaybeScopedRefPtr() {} |
| 451 }; | 436 }; |
| (...skipping 197 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 649 BASE_EXPORT void DoNothing(); | 634 BASE_EXPORT void DoNothing(); |
| 650 | 635 |
| 651 template<typename T> | 636 template<typename T> |
| 652 void DeletePointer(T* obj) { | 637 void DeletePointer(T* obj) { |
| 653 delete obj; | 638 delete obj; |
| 654 } | 639 } |
| 655 | 640 |
| 656 } // namespace base | 641 } // namespace base |
| 657 | 642 |
| 658 #endif // BASE_BIND_HELPERS_H_ | 643 #endif // BASE_BIND_HELPERS_H_ |
| OLD | NEW |