OLD | NEW |
1 /* | 1 /* |
2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. | 2 * Copyright 2012 The WebRTC Project Authors. All rights reserved. |
3 * | 3 * |
4 * Use of this source code is governed by a BSD-style license | 4 * Use of this source code is governed by a BSD-style license |
5 * that can be found in the LICENSE file in the root of the source | 5 * that can be found in the LICENSE file in the root of the source |
6 * tree. An additional intellectual property rights grant can be found | 6 * tree. An additional intellectual property rights grant can be found |
7 * in the file PATENTS. All contributing project authors may | 7 * in the file PATENTS. All contributing project authors may |
8 * be found in the AUTHORS file in the root of the source tree. | 8 * be found in the AUTHORS file in the root of the source tree. |
9 */ | 9 */ |
10 | 10 |
11 // To generate bind.h from bind.h.pump, execute: | 11 // To generate bind.h from bind.h.pump, execute: |
12 // /home/build/google3/third_party/gtest/scripts/pump.py bind.h.pump | 12 // /home/build/google3/third_party/gtest/scripts/pump.py bind.h.pump |
13 | 13 |
14 // Bind() is an overloaded function that converts method calls into function | 14 // Bind() is an overloaded function that converts method calls into function |
15 // objects (aka functors). It captures any arguments to the method by value | 15 // objects (aka functors). The method object is captured as a scoped_refptr<> if |
16 // when Bind is called, producing a stateful, nullary function object. Care | 16 // possible, and as a raw pointer otherwise. Any arguments to the method are |
17 // should be taken about the lifetime of objects captured by Bind(); the | 17 // captured by value. The return value of Bind is a stateful, nullary function |
18 // returned functor knows nothing about the lifetime of the method's object or | 18 // object. Care should be taken about the lifetime of objects captured by |
19 // any arguments passed by pointer, and calling the functor with a destroyed | 19 // Bind(); the returned functor knows nothing about the lifetime of a non |
20 // object will surely do bad things. | 20 // ref-counted method object or any arguments passed by pointer, and calling the |
| 21 // functor with a destroyed object will surely do bad things. |
21 // | 22 // |
22 // Example usage: | 23 // Example usage: |
23 // struct Foo { | 24 // struct Foo { |
24 // int Test1() { return 42; } | 25 // int Test1() { return 42; } |
25 // int Test2() const { return 52; } | 26 // int Test2() const { return 52; } |
26 // int Test3(int x) { return x*x; } | 27 // int Test3(int x) { return x*x; } |
27 // float Test4(int x, float y) { return x + y; } | 28 // float Test4(int x, float y) { return x + y; } |
28 // }; | 29 // }; |
29 // | 30 // |
30 // int main() { | 31 // int main() { |
31 // Foo foo; | 32 // Foo foo; |
32 // cout << rtc::Bind(&Foo::Test1, &foo)() << endl; | 33 // cout << rtc::Bind(&Foo::Test1, &foo)() << endl; |
33 // cout << rtc::Bind(&Foo::Test2, &foo)() << endl; | 34 // cout << rtc::Bind(&Foo::Test2, &foo)() << endl; |
34 // cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl; | 35 // cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl; |
35 // cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl; | 36 // cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl; |
36 // } | 37 // } |
| 38 // |
| 39 // Example usage of ref counted objects: |
| 40 // struct Bar { |
| 41 // int AddRef(); |
| 42 // int Release(); |
| 43 // |
| 44 // void Test() {} |
| 45 // void BindThis() { |
| 46 // // The functor passed to AsyncInvoke() will keep this object alive. |
| 47 // invoker.AsyncInvoke(rtc::Bind(&Bar::Test, this)); |
| 48 // } |
| 49 // }; |
| 50 // |
| 51 // int main() { |
| 52 // rtc::scoped_refptr<Bar> bar = new rtc::RefCountedObject<Bar>(); |
| 53 // auto functor = rtc::Bind(&Bar::Test, bar); |
| 54 // bar = nullptr; |
| 55 // // The functor stores an internal scoped_refptr<Bar>, so this is safe. |
| 56 // functor(); |
| 57 // } |
| 58 // |
37 | 59 |
38 #ifndef WEBRTC_BASE_BIND_H_ | 60 #ifndef WEBRTC_BASE_BIND_H_ |
39 #define WEBRTC_BASE_BIND_H_ | 61 #define WEBRTC_BASE_BIND_H_ |
40 | 62 |
| 63 #include "webrtc/base/scoped_ref_ptr.h" |
| 64 |
41 #define NONAME | 65 #define NONAME |
42 | 66 |
43 namespace rtc { | 67 namespace rtc { |
44 namespace detail { | 68 namespace detail { |
45 // This is needed because the template parameters in Bind can't be resolved | 69 // This is needed because the template parameters in Bind can't be resolved |
46 // if they're used both as parameters of the function pointer type and as | 70 // if they're used both as parameters of the function pointer type and as |
47 // parameters to Bind itself: the function pointer parameters are exact | 71 // parameters to Bind itself: the function pointer parameters are exact |
48 // matches to the function prototype, but the parameters to bind have | 72 // matches to the function prototype, but the parameters to bind have |
49 // references stripped. This trick allows the compiler to dictate the Bind | 73 // references stripped. This trick allows the compiler to dictate the Bind |
50 // parameter types rather than deduce them. | 74 // parameter types rather than deduce them. |
51 template <class T> struct identity { typedef T type; }; | 75 template <class T> struct identity { typedef T type; }; |
| 76 |
| 77 // IsRefCounted<T>::value will be true for types that can be used in |
| 78 // rtc::scoped_refptr<T>, i.e. types that implements nullary functions AddRef() |
| 79 // and Release(), regardless of their return types. AddRef() and Release() can |
| 80 // be defined in T or any superclass of T. |
| 81 template <typename T> |
| 82 class IsRefCounted { |
| 83 // This is a complex implementation detail done with SFINAE. |
| 84 |
| 85 // Define types such that sizeof(Yes) != sizeof(No). |
| 86 struct Yes { char dummy[1]; }; |
| 87 struct No { char dummy[2]; }; |
| 88 // Define two overloaded template functions with return types of different |
| 89 // size. This way, we can use sizeof() on the return type to determine which |
| 90 // function the compiler would have chosen. One function will be preferred |
| 91 // over the other if it is possible to create it without compiler errors, |
| 92 // otherwise the compiler will simply remove it, and default to the less |
| 93 // preferred function. |
| 94 template <typename R> |
| 95 static Yes test(R* r, decltype(r->AddRef(), r->Release(), 42)); |
| 96 template <typename C> static No test(...); |
| 97 |
| 98 public: |
| 99 // Trick the compiler to tell if it's possible to call AddRef() and Release(). |
| 100 static const bool value = sizeof(test<T>((T*)nullptr, 42)) == sizeof(Yes); |
| 101 }; |
| 102 |
| 103 // TernaryTypeOperator is a helper class to select a type based on a static bool |
| 104 // value. |
| 105 template <bool condition, typename IfTrueT, typename IfFalseT> |
| 106 struct TernaryTypeOperator {}; |
| 107 |
| 108 template <typename IfTrueT, typename IfFalseT> |
| 109 struct TernaryTypeOperator<true, IfTrueT, IfFalseT> { |
| 110 typedef IfTrueT type; |
| 111 }; |
| 112 |
| 113 template <typename IfTrueT, typename IfFalseT> |
| 114 struct TernaryTypeOperator<false, IfTrueT, IfFalseT> { |
| 115 typedef IfFalseT type; |
| 116 }; |
| 117 |
| 118 // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T* |
| 119 // otherwise. |
| 120 template <class T> |
| 121 struct PointerType { |
| 122 typedef typename TernaryTypeOperator<IsRefCounted<T>::value, |
| 123 scoped_refptr<T>, |
| 124 T*>::type type; |
| 125 }; |
| 126 |
52 } // namespace detail | 127 } // namespace detail |
53 | 128 |
54 $var n = 6 | 129 $var n = 6 |
55 $range i 0..n | 130 $range i 0..n |
56 $for i [[ | 131 $for i [[ |
57 $range j 1..i | 132 $range j 1..i |
58 | 133 |
59 template <class ObjectT, class MethodT, class R$for j [[, | 134 template <class ObjectT, class MethodT, class R$for j [[, |
60 class P$j]]> | 135 class P$j]]> |
61 class MethodFunctor$i { | 136 class MethodFunctor$i { |
62 public: | 137 public: |
63 MethodFunctor$i(MethodT method, ObjectT* object$for j [[, | 138 MethodFunctor$i(MethodT method, ObjectT* object$for j [[, |
64 P$j p$j]]) | 139 P$j p$j]]) |
65 : method_(method), object_(object)$for j [[, | 140 : method_(method), object_(object)$for j [[, |
66 p$(j)_(p$j)]] {} | 141 p$(j)_(p$j)]] {} |
67 R operator()() const { | 142 R operator()() const { |
68 return (object_->*method_)($for j , [[p$(j)_]]); } | 143 return (object_->*method_)($for j , [[p$(j)_]]); } |
69 private: | 144 private: |
70 MethodT method_; | 145 MethodT method_; |
71 ObjectT* object_;$for j [[ | 146 typename detail::PointerType<ObjectT>::type object_;$for j [[ |
72 | 147 |
73 P$j p$(j)_;]] | 148 P$j p$(j)_;]] |
74 | 149 |
75 }; | 150 }; |
76 | 151 |
77 template <class FunctorT, class R$for j [[, | 152 template <class FunctorT, class R$for j [[, |
78 class P$j]]> | 153 class P$j]]> |
79 class Functor$i { | 154 class Functor$i { |
80 public: | 155 public: |
81 $if i == 0 [[explicit ]] | 156 $if i == 0 [[explicit ]] |
(...skipping 27 matching lines...) Expand all Loading... |
109 template <class ObjectT, class R$for j [[, | 184 template <class ObjectT, class R$for j [[, |
110 class P$j]]> | 185 class P$j]]> |
111 MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]> | 186 MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]> |
112 Bind(FP_T(method), const ObjectT* object$for j [[, | 187 Bind(FP_T(method), const ObjectT* object$for j [[, |
113 typename detail::identity<P$j>::type p$j]]) { | 188 typename detail::identity<P$j>::type p$j]]) { |
114 return MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( | 189 return MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( |
115 method, object$for j [[, p$j]]); | 190 method, object$for j [[, p$j]]); |
116 } | 191 } |
117 | 192 |
118 #undef FP_T | 193 #undef FP_T |
| 194 #define FP_T(x) R (ObjectT::*x)($for j , [[P$j]]) |
| 195 |
| 196 template <class ObjectT, class R$for j [[, |
| 197 class P$j]]> |
| 198 MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]> |
| 199 Bind(FP_T(method), const scoped_refptr<ObjectT>& object$for j [[, |
| 200 typename detail::identity<P$j>::type p$j]]) { |
| 201 return MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( |
| 202 method, object.get()$for j [[, p$j]]); |
| 203 } |
| 204 |
| 205 #undef FP_T |
119 #define FP_T(x) R (*x)($for j , [[P$j]]) | 206 #define FP_T(x) R (*x)($for j , [[P$j]]) |
120 | 207 |
121 template <class R$for j [[, | 208 template <class R$for j [[, |
122 class P$j]]> | 209 class P$j]]> |
123 Functor$i<FP_T(NONAME), R$for j [[, P$j]]> | 210 Functor$i<FP_T(NONAME), R$for j [[, P$j]]> |
124 Bind(FP_T(function)$for j [[, | 211 Bind(FP_T(function)$for j [[, |
125 typename detail::identity<P$j>::type p$j]]) { | 212 typename detail::identity<P$j>::type p$j]]) { |
126 return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>( | 213 return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>( |
127 function$for j [[, p$j]]); | 214 function$for j [[, p$j]]); |
128 } | 215 } |
129 | 216 |
130 #undef FP_T | 217 #undef FP_T |
131 | 218 |
132 ]] | 219 ]] |
133 | 220 |
134 } // namespace rtc | 221 } // namespace rtc |
135 | 222 |
136 #undef NONAME | 223 #undef NONAME |
137 | 224 |
138 #endif // WEBRTC_BASE_BIND_H_ | 225 #endif // WEBRTC_BASE_BIND_H_ |
OLD | NEW |