| 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 // Bind() is an overloaded function that converts method calls into function | 11 // Bind() is an overloaded function that converts method calls into function |
| 12 // objects (aka functors). The method object is captured as a scoped_refptr<> if | 12 // objects (aka functors). The method object is captured as a scoped_refptr<> if |
| 13 // possible, and as a raw pointer otherwise. Any arguments to the method are | 13 // possible, and as a raw pointer otherwise. Any arguments to the method are |
| 14 // captured by value. The return value of Bind is a stateful, nullary function | 14 // captured by value. The return value of Bind is a stateful, nullary function |
| 15 // object. Care should be taken about the lifetime of objects captured by | 15 // object. Care should be taken about the lifetime of objects captured by |
| 16 // Bind(); the returned functor knows nothing about the lifetime of a non | 16 // Bind(); the returned functor knows nothing about the lifetime of a non |
| 17 // ref-counted method object or any arguments passed by pointer, and calling the | 17 // ref-counted method object or any arguments passed by pointer, and calling the |
| 18 // functor with a destroyed object will surely do bad things. | 18 // functor with a destroyed object will surely do bad things. |
| 19 // | 19 // |
| 20 // To prevent the method object from being captured as a scoped_refptr<>, you |
| 21 // can use Unretained. But this should only be done when absolutely necessary, |
| 22 // and when the caller knows the extra reference isn't needed. |
| 23 // |
| 20 // Example usage: | 24 // Example usage: |
| 21 // struct Foo { | 25 // struct Foo { |
| 22 // int Test1() { return 42; } | 26 // int Test1() { return 42; } |
| 23 // int Test2() const { return 52; } | 27 // int Test2() const { return 52; } |
| 24 // int Test3(int x) { return x*x; } | 28 // int Test3(int x) { return x*x; } |
| 25 // float Test4(int x, float y) { return x + y; } | 29 // float Test4(int x, float y) { return x + y; } |
| 26 // }; | 30 // }; |
| 27 // | 31 // |
| 28 // int main() { | 32 // int main() { |
| 29 // Foo foo; | 33 // Foo foo; |
| (...skipping 88 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
| 118 | 122 |
| 119 // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T* | 123 // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T* |
| 120 // otherwise. | 124 // otherwise. |
| 121 template <class T> | 125 template <class T> |
| 122 struct PointerType { | 126 struct PointerType { |
| 123 typedef typename TernaryTypeOperator<IsRefCounted<T>::value, | 127 typedef typename TernaryTypeOperator<IsRefCounted<T>::value, |
| 124 scoped_refptr<T>, | 128 scoped_refptr<T>, |
| 125 T*>::type type; | 129 T*>::type type; |
| 126 }; | 130 }; |
| 127 | 131 |
| 132 template <typename T> |
| 133 class UnretainedWrapper { |
| 134 public: |
| 135 explicit UnretainedWrapper(T* o) : ptr_(o) {} |
| 136 T* get() const { return ptr_; } |
| 137 |
| 138 private: |
| 139 T* ptr_; |
| 140 }; |
| 141 |
| 128 } // namespace detail | 142 } // namespace detail |
| 129 | 143 |
| 144 template <typename T> |
| 145 static inline detail::UnretainedWrapper<T> Unretained(T* o) { |
| 146 return detail::UnretainedWrapper<T>(o); |
| 147 } |
| 148 |
| 130 template <class ObjectT, class MethodT, class R, typename... Args> | 149 template <class ObjectT, class MethodT, class R, typename... Args> |
| 131 class MethodFunctor { | 150 class MethodFunctor { |
| 132 public: | 151 public: |
| 133 MethodFunctor(MethodT method, ObjectT* object, Args... args) | 152 MethodFunctor(MethodT method, ObjectT* object, Args... args) |
| 134 : method_(method), object_(object), args_(args...) {} | 153 : method_(method), object_(object), args_(args...) {} |
| 135 R operator()() const { | 154 R operator()() const { |
| 136 return CallMethod(typename sequence_generator<sizeof...(Args)>::type()); | 155 return CallMethod(typename sequence_generator<sizeof...(Args)>::type()); |
| 137 } | 156 } |
| 138 | 157 |
| 139 private: | 158 private: |
| 140 // Use sequence_generator (see template_util.h) to expand a MethodFunctor | 159 // Use sequence_generator (see template_util.h) to expand a MethodFunctor |
| 141 // with 2 arguments to (std::get<0>(args_), std::get<1>(args_)), for | 160 // with 2 arguments to (std::get<0>(args_), std::get<1>(args_)), for |
| 142 // instance. | 161 // instance. |
| 143 template <int... S> | 162 template <int... S> |
| 144 R CallMethod(sequence<S...>) const { | 163 R CallMethod(sequence<S...>) const { |
| 145 return (object_->*method_)(std::get<S>(args_)...); | 164 return (object_->*method_)(std::get<S>(args_)...); |
| 146 } | 165 } |
| 147 | 166 |
| 148 MethodT method_; | 167 MethodT method_; |
| 149 typename detail::PointerType<ObjectT>::type object_; | 168 typename detail::PointerType<ObjectT>::type object_; |
| 150 typename std::tuple<typename std::remove_reference<Args>::type...> args_; | 169 typename std::tuple<typename std::remove_reference<Args>::type...> args_; |
| 151 }; | 170 }; |
| 152 | 171 |
| 172 template <class ObjectT, class MethodT, class R, typename... Args> |
| 173 class UnretainedMethodFunctor { |
| 174 public: |
| 175 UnretainedMethodFunctor(MethodT method, |
| 176 detail::UnretainedWrapper<ObjectT> object, |
| 177 Args... args) |
| 178 : method_(method), object_(object.get()), args_(args...) {} |
| 179 R operator()() const { |
| 180 return CallMethod(typename sequence_generator<sizeof...(Args)>::type()); |
| 181 } |
| 182 |
| 183 private: |
| 184 // Use sequence_generator (see template_util.h) to expand an |
| 185 // UnretainedMethodFunctor with 2 arguments to (std::get<0>(args_), |
| 186 // std::get<1>(args_)), for instance. |
| 187 template <int... S> |
| 188 R CallMethod(sequence<S...>) const { |
| 189 return (object_->*method_)(std::get<S>(args_)...); |
| 190 } |
| 191 |
| 192 MethodT method_; |
| 193 ObjectT* object_; |
| 194 typename std::tuple<typename std::remove_reference<Args>::type...> args_; |
| 195 }; |
| 196 |
| 153 template <class FunctorT, class R, typename... Args> | 197 template <class FunctorT, class R, typename... Args> |
| 154 class Functor { | 198 class Functor { |
| 155 public: | 199 public: |
| 156 Functor(const FunctorT& functor, Args... args) | 200 Functor(const FunctorT& functor, Args... args) |
| 157 : functor_(functor), args_(args...) {} | 201 : functor_(functor), args_(args...) {} |
| 158 R operator()() const { | 202 R operator()() const { |
| 159 return CallFunction(typename sequence_generator<sizeof...(Args)>::type()); | 203 return CallFunction(typename sequence_generator<sizeof...(Args)>::type()); |
| 160 } | 204 } |
| 161 | 205 |
| 162 private: | 206 private: |
| (...skipping 13 matching lines...) Expand all Loading... |
| 176 | 220 |
| 177 template <class ObjectT, class R, typename... Args> | 221 template <class ObjectT, class R, typename... Args> |
| 178 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( | 222 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 179 FP_T(method), | 223 FP_T(method), |
| 180 ObjectT* object, | 224 ObjectT* object, |
| 181 typename detail::identity<Args>::type... args) { | 225 typename detail::identity<Args>::type... args) { |
| 182 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object, | 226 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object, |
| 183 args...); | 227 args...); |
| 184 } | 228 } |
| 185 | 229 |
| 230 template <class ObjectT, class R, typename... Args> |
| 231 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 232 FP_T(method), |
| 233 const scoped_refptr<ObjectT>& object, |
| 234 typename detail::identity<Args>::type... args) { |
| 235 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(), |
| 236 args...); |
| 237 } |
| 238 |
| 239 template <class ObjectT, class R, typename... Args> |
| 240 UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 241 FP_T(method), |
| 242 detail::UnretainedWrapper<ObjectT> object, |
| 243 typename detail::identity<Args>::type... args) { |
| 244 return UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...>( |
| 245 method, object, args...); |
| 246 } |
| 247 |
| 186 #undef FP_T | 248 #undef FP_T |
| 187 #define FP_T(x) R (ObjectT::*x)(Args...) const | 249 #define FP_T(x) R (ObjectT::*x)(Args...) const |
| 188 | 250 |
| 189 template <class ObjectT, class R, typename... Args> | 251 template <class ObjectT, class R, typename... Args> |
| 190 MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind( | 252 MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 191 FP_T(method), | 253 FP_T(method), |
| 192 const ObjectT* object, | 254 const ObjectT* object, |
| 193 typename detail::identity<Args>::type... args) { | 255 typename detail::identity<Args>::type... args) { |
| 194 return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object, | 256 return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object, |
| 195 args...); | 257 args...); |
| 196 } | 258 } |
| 197 | |
| 198 #undef FP_T | |
| 199 #define FP_T(x) R (ObjectT::*x)(Args...) | |
| 200 | |
| 201 template <class ObjectT, class R, typename... Args> | 259 template <class ObjectT, class R, typename... Args> |
| 202 MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind( | 260 UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind( |
| 203 FP_T(method), | 261 FP_T(method), |
| 204 const scoped_refptr<ObjectT>& object, | 262 detail::UnretainedWrapper<const ObjectT> object, |
| 205 typename detail::identity<Args>::type... args) { | 263 typename detail::identity<Args>::type... args) { |
| 206 return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(), | 264 return UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>( |
| 207 args...); | 265 method, object, args...); |
| 208 } | 266 } |
| 209 | 267 |
| 210 #undef FP_T | 268 #undef FP_T |
| 211 #define FP_T(x) R (*x)(Args...) | 269 #define FP_T(x) R (*x)(Args...) |
| 212 | 270 |
| 213 template <class R, typename... Args> | 271 template <class R, typename... Args> |
| 214 Functor<FP_T(NONAME), R, Args...> Bind( | 272 Functor<FP_T(NONAME), R, Args...> Bind( |
| 215 FP_T(function), | 273 FP_T(function), |
| 216 typename detail::identity<Args>::type... args) { | 274 typename detail::identity<Args>::type... args) { |
| 217 return Functor<FP_T(NONAME), R, Args...>(function, args...); | 275 return Functor<FP_T(NONAME), R, Args...>(function, args...); |
| 218 } | 276 } |
| 219 | 277 |
| 220 #undef FP_T | 278 #undef FP_T |
| 221 | 279 |
| 222 } // namespace rtc | 280 } // namespace rtc |
| 223 | 281 |
| 224 #undef NONAME | 282 #undef NONAME |
| 225 | 283 |
| 226 #endif // WEBRTC_BASE_BIND_H_ | 284 #endif // WEBRTC_BASE_BIND_H_ |
| OLD | NEW |