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 // the class inherits from RefCountInterface, and as a raw pointer otherwise. |
17 // should be taken about the lifetime of objects captured by Bind(); the | 17 // Any arguments to the method are captured by value. The return value of Bind |
18 // returned functor knows nothing about the lifetime of the method's object or | 18 // is a stateful, nullary function object. Care should be taken about the |
19 // any arguments passed by pointer, and calling the functor with a destroyed | 19 // lifetime of objects captured by Bind(); the returned functor knows nothing |
20 // object will surely do bad things. | 20 // about the lifetime of a non ref-counted method object or any arguments passed |
| 21 // by pointer, and calling the functor with a destroyed object will surely do |
| 22 // bad things. |
21 // | 23 // |
22 // Example usage: | 24 // Example usage: |
23 // struct Foo { | 25 // struct Foo { |
24 // int Test1() { return 42; } | 26 // int Test1() { return 42; } |
25 // int Test2() const { return 52; } | 27 // int Test2() const { return 52; } |
26 // int Test3(int x) { return x*x; } | 28 // int Test3(int x) { return x*x; } |
27 // float Test4(int x, float y) { return x + y; } | 29 // float Test4(int x, float y) { return x + y; } |
28 // }; | 30 // }; |
29 // | 31 // |
30 // int main() { | 32 // int main() { |
31 // Foo foo; | 33 // Foo foo; |
32 // cout << rtc::Bind(&Foo::Test1, &foo)() << endl; | 34 // cout << rtc::Bind(&Foo::Test1, &foo)() << endl; |
33 // cout << rtc::Bind(&Foo::Test2, &foo)() << endl; | 35 // cout << rtc::Bind(&Foo::Test2, &foo)() << endl; |
34 // cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl; | 36 // cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl; |
35 // cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl; | 37 // cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl; |
36 // } | 38 // } |
| 39 // |
| 40 // Example usage for ref counted objects: |
| 41 // struct Bar : public rtc::RefCountInterface { |
| 42 // void Test() {} |
| 43 // void BindThis() { |
| 44 // // The functor passed to AsyncInvoke() will keep this object alive. |
| 45 // invoker.AsyncInvoke(rtc::Bind(&Bar::Test, this)); |
| 46 // } |
| 47 // }; |
| 48 // |
| 49 // int main() { |
| 50 // rtc::scoped_refptr<Bar> bar = new rtc::RefCountedObject<Bar>(); |
| 51 // auto functor = rtc::Bind(&Bar::Test, bar); |
| 52 // bar = nullptr; |
| 53 // // The functor stores an internal scoped_refptr<Bar>, so this is safe. |
| 54 // functor(); |
| 55 // } |
| 56 // |
37 | 57 |
38 #ifndef WEBRTC_BASE_BIND_H_ | 58 #ifndef WEBRTC_BASE_BIND_H_ |
39 #define WEBRTC_BASE_BIND_H_ | 59 #define WEBRTC_BASE_BIND_H_ |
40 | 60 |
| 61 #include "webrtc/base/refcount.h" |
| 62 #include "webrtc/base/scoped_ref_ptr.h" |
| 63 #include "webrtc/base/template_util.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 is a static bool that represents if T implements |
| 78 // RefCountInterface. rtc::is_convertible<> does the heavy lifting. It is a |
| 79 // substitute for C++11 std::is_convertible<>. |
| 80 template <class T> |
| 81 struct IsRefCounted { |
| 82 static const bool value = is_convertible<T*, RefCountInterface*>::value; |
| 83 }; |
| 84 |
| 85 // TernaryTypeOperator is a helper class to select a type based on a static bool |
| 86 // value. |
| 87 template <bool condition, typename IfTrueT, typename IfFalseT> |
| 88 struct TernaryTypeOperator {}; |
| 89 |
| 90 template <typename IfTrueT, typename IfFalseT> |
| 91 struct TernaryTypeOperator<true, IfTrueT, IfFalseT> { |
| 92 typedef IfTrueT type; |
| 93 }; |
| 94 |
| 95 template <typename IfTrueT, typename IfFalseT> |
| 96 struct TernaryTypeOperator<false, IfTrueT, IfFalseT> { |
| 97 typedef IfFalseT type; |
| 98 }; |
| 99 |
| 100 // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T* |
| 101 // otherwise. |
| 102 template <class T> |
| 103 struct PointerType { |
| 104 typedef typename TernaryTypeOperator<IsRefCounted<T>::value, |
| 105 scoped_refptr<T>, |
| 106 T*>::type type; |
| 107 }; |
| 108 |
52 } // namespace detail | 109 } // namespace detail |
53 | 110 |
54 $var n = 6 | 111 $var n = 6 |
55 $range i 0..n | 112 $range i 0..n |
56 $for i [[ | 113 $for i [[ |
57 $range j 1..i | 114 $range j 1..i |
58 | 115 |
59 template <class ObjectT, class MethodT, class R$for j [[, | 116 template <class ObjectT, class MethodT, class R$for j [[, |
60 class P$j]]> | 117 class P$j]]> |
61 class MethodFunctor$i { | 118 class MethodFunctor$i { |
62 public: | 119 public: |
63 MethodFunctor$i(MethodT method, ObjectT* object$for j [[, | 120 MethodFunctor$i(MethodT method, ObjectT* object$for j [[, |
64 P$j p$j]]) | 121 P$j p$j]]) |
65 : method_(method), object_(object)$for j [[, | 122 : method_(method), object_(object)$for j [[, |
66 p$(j)_(p$j)]] {} | 123 p$(j)_(p$j)]] {} |
67 R operator()() const { | 124 R operator()() const { |
68 return (object_->*method_)($for j , [[p$(j)_]]); } | 125 return (object_->*method_)($for j , [[p$(j)_]]); } |
69 private: | 126 private: |
70 MethodT method_; | 127 MethodT method_; |
71 ObjectT* object_;$for j [[ | 128 typename detail::PointerType<ObjectT>::type object_;$for j [[ |
72 | 129 |
73 P$j p$(j)_;]] | 130 P$j p$(j)_;]] |
74 | 131 |
75 }; | 132 }; |
76 | 133 |
77 template <class FunctorT, class R$for j [[, | 134 template <class FunctorT, class R$for j [[, |
78 class P$j]]> | 135 class P$j]]> |
79 class Functor$i { | 136 class Functor$i { |
80 public: | 137 public: |
81 $if i == 0 [[explicit ]] | 138 $if i == 0 [[explicit ]] |
(...skipping 27 matching lines...) Expand all Loading... |
109 template <class ObjectT, class R$for j [[, | 166 template <class ObjectT, class R$for j [[, |
110 class P$j]]> | 167 class P$j]]> |
111 MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]> | 168 MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]> |
112 Bind(FP_T(method), const ObjectT* object$for j [[, | 169 Bind(FP_T(method), const ObjectT* object$for j [[, |
113 typename detail::identity<P$j>::type p$j]]) { | 170 typename detail::identity<P$j>::type p$j]]) { |
114 return MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( | 171 return MethodFunctor$i<const ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( |
115 method, object$for j [[, p$j]]); | 172 method, object$for j [[, p$j]]); |
116 } | 173 } |
117 | 174 |
118 #undef FP_T | 175 #undef FP_T |
| 176 #define FP_T(x) R (ObjectT::*x)($for j , [[P$j]]) |
| 177 |
| 178 template <class ObjectT, class R$for j [[, |
| 179 class P$j]]> |
| 180 MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]> |
| 181 Bind(FP_T(method), const scoped_refptr<ObjectT>& object$for j [[, |
| 182 typename detail::identity<P$j>::type p$j]]) { |
| 183 return MethodFunctor$i<ObjectT, FP_T(NONAME), R$for j [[, P$j]]>( |
| 184 method, object.get()$for j [[, p$j]]); |
| 185 } |
| 186 |
| 187 #undef FP_T |
119 #define FP_T(x) R (*x)($for j , [[P$j]]) | 188 #define FP_T(x) R (*x)($for j , [[P$j]]) |
120 | 189 |
121 template <class R$for j [[, | 190 template <class R$for j [[, |
122 class P$j]]> | 191 class P$j]]> |
123 Functor$i<FP_T(NONAME), R$for j [[, P$j]]> | 192 Functor$i<FP_T(NONAME), R$for j [[, P$j]]> |
124 Bind(FP_T(function)$for j [[, | 193 Bind(FP_T(function)$for j [[, |
125 typename detail::identity<P$j>::type p$j]]) { | 194 typename detail::identity<P$j>::type p$j]]) { |
126 return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>( | 195 return Functor$i<FP_T(NONAME), R$for j [[, P$j]]>( |
127 function$for j [[, p$j]]); | 196 function$for j [[, p$j]]); |
128 } | 197 } |
129 | 198 |
130 #undef FP_T | 199 #undef FP_T |
131 | 200 |
132 ]] | 201 ]] |
133 | 202 |
134 } // namespace rtc | 203 } // namespace rtc |
135 | 204 |
136 #undef NONAME | 205 #undef NONAME |
137 | 206 |
138 #endif // WEBRTC_BASE_BIND_H_ | 207 #endif // WEBRTC_BASE_BIND_H_ |
OLD | NEW |