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 |