OLD | NEW |
(Empty) | |
| 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 |
| 3 // found in the LICENSE file. |
| 4 |
| 5 // This defines a set of argument wrappers, and related factory methods for |
| 6 // changing the refcounting, and reference semantics of arguments that are bound |
| 7 // by the Prebind() function in base/prebind.h. |
| 8 // |
| 9 // The public functions are base::Unretained() and base::ConstRef(). |
| 10 // Unretained() allows Prebind() to bind a non-refcounted class. ConstRef() |
| 11 // allows binding a constant reference to an argument rather than a copy. |
| 12 // |
| 13 // |
| 14 // EXAMPLE OF Unretained(): |
| 15 // |
| 16 // class Foo { |
| 17 // public: |
| 18 // void func() { cout << "Foo:f" << endl; |
| 19 // }; |
| 20 // |
| 21 // // In some function somewhere. |
| 22 // Foo foo; |
| 23 // Callback<void(void)> foo_callback = Prebind(&Foo::func, Unretained(&foo)); |
| 24 // foo_callback.Run(); // Prints "Foo:f". |
| 25 // |
| 26 // Without the Unretained() wrapper on |&foo|, the above call would fail to |
| 27 // compile because Foo does not support the AddRef() and Release() methods. |
| 28 // |
| 29 // |
| 30 // EXAMPLE OF ConstRef(); |
| 31 // void foo(int arg) { cout << arg << endl } |
| 32 // |
| 33 // int n = 1; |
| 34 // Callback<void(void)> no_ref = Prebind(&foo, n); |
| 35 // Callback<void(void)> has_ref = Prebind(&foo, ConstRef(n)); |
| 36 // |
| 37 // no_ref.Run(); // Prints "1" |
| 38 // has_ref.Run(); // Prints "1" |
| 39 // |
| 40 // n = 2; |
| 41 // no_ref.Run(); // Prints "1" |
| 42 // has_ref.Run(); // Prints "2" |
| 43 // |
| 44 // Note that because ConstRef() takes a reference on |n|, |n| must outlive all |
| 45 // its bound callbacks. |
| 46 // |
| 47 |
| 48 #ifndef BASE_PREBIND_HELPERS_H_ |
| 49 #define BASE_PREBIND_HELPERS_H_ |
| 50 #pragma once |
| 51 |
| 52 namespace base { |
| 53 |
| 54 namespace internal { |
| 55 template <typename T> |
| 56 class UnretainedWrapper { |
| 57 public: |
| 58 explicit UnretainedWrapper(T* o) : obj_(o) {} |
| 59 T* get() { return obj_; } |
| 60 private: |
| 61 T* obj_; |
| 62 }; |
| 63 |
| 64 template <typename T> |
| 65 class ConstRefWrapper { |
| 66 public: |
| 67 explicit ConstRefWrapper(const T& o) : ptr_(&o) {} |
| 68 const T& get() { return *ptr_; } |
| 69 private: |
| 70 const T* ptr_; |
| 71 }; |
| 72 |
| 73 |
| 74 // Unwrap the stored parameters for the wrappers above. |
| 75 template <typename T> |
| 76 T Unwrap(T o) { return o; } |
| 77 |
| 78 template <typename T> |
| 79 T* Unwrap(UnretainedWrapper<T> unretained) { return unretained.get(); } |
| 80 |
| 81 template <typename T> |
| 82 const T& Unwrap(ConstRefWrapper<T> const_ref) { return const_ref.get(); } |
| 83 |
| 84 |
| 85 // Utility for handling different refcounting semantics in the Prebind() |
| 86 // function. |
| 87 template <bool ref, typename O> |
| 88 struct MaybeRefcount; |
| 89 |
| 90 template <typename O> |
| 91 struct MaybeRefcount<false, O> { |
| 92 static void AddRef(const O&) {} |
| 93 static void Release(const O&) {} |
| 94 }; |
| 95 |
| 96 template <typename O> |
| 97 struct MaybeRefcount<true, UnretainedWrapper<O> > { |
| 98 static void AddRef(const UnretainedWrapper<O>&) {} |
| 99 static void Release(const UnretainedWrapper<O>&) {} |
| 100 }; |
| 101 |
| 102 template <typename O> |
| 103 struct MaybeRefcount<true, O* > { |
| 104 static void AddRef(O* o) { o->AddRef(); } |
| 105 static void Release(O* o) { o->Release(); } |
| 106 }; |
| 107 |
| 108 template <typename O> |
| 109 struct MaybeRefcount<true, const O* > { |
| 110 static void AddRef(const O* o) { o->AddRef(); } |
| 111 static void Release(const O* o) { o->Release(); } |
| 112 }; |
| 113 |
| 114 } // namespace internal |
| 115 |
| 116 template <typename T> |
| 117 inline internal::UnretainedWrapper<T> Unretained(T* o) { |
| 118 return internal::UnretainedWrapper<T>(o); |
| 119 } |
| 120 |
| 121 template <typename T> |
| 122 inline internal::ConstRefWrapper<T> ConstRef(const T& o) { |
| 123 return internal::ConstRefWrapper<T>(o); |
| 124 } |
| 125 |
| 126 } // namespace base |
| 127 |
| 128 #endif // BASE_PREBIND_HELPERS_H_ |
OLD | NEW |