| 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 |