bind.h 9.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282
  1. /*
  2. * Copyright 2012 The WebRTC Project Authors. All rights reserved.
  3. *
  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
  6. * tree. An additional intellectual property rights grant can be found
  7. * in the file PATENTS. All contributing project authors may
  8. * be found in the AUTHORS file in the root of the source tree.
  9. */
  10. // Bind() is an overloaded function that converts method calls into function
  11. // objects (aka functors). The method object is captured as a scoped_refptr<> if
  12. // possible, and as a raw pointer otherwise. Any arguments to the method are
  13. // captured by value. The return value of Bind is a stateful, nullary function
  14. // object. Care should be taken about the lifetime of objects captured by
  15. // Bind(); the returned functor knows nothing about the lifetime of a non
  16. // ref-counted method object or any arguments passed by pointer, and calling the
  17. // functor with a destroyed object will surely do bad things.
  18. //
  19. // To prevent the method object from being captured as a scoped_refptr<>, you
  20. // can use Unretained. But this should only be done when absolutely necessary,
  21. // and when the caller knows the extra reference isn't needed.
  22. //
  23. // Example usage:
  24. // struct Foo {
  25. // int Test1() { return 42; }
  26. // int Test2() const { return 52; }
  27. // int Test3(int x) { return x*x; }
  28. // float Test4(int x, float y) { return x + y; }
  29. // };
  30. //
  31. // int main() {
  32. // Foo foo;
  33. // cout << rtc::Bind(&Foo::Test1, &foo)() << endl;
  34. // cout << rtc::Bind(&Foo::Test2, &foo)() << endl;
  35. // cout << rtc::Bind(&Foo::Test3, &foo, 3)() << endl;
  36. // cout << rtc::Bind(&Foo::Test4, &foo, 7, 8.5f)() << endl;
  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_FROM_HERE,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. //
  59. #ifndef RTC_BASE_BIND_H_
  60. #define RTC_BASE_BIND_H_
  61. #include <tuple>
  62. #include <type_traits>
  63. #include "api/scoped_refptr.h"
  64. #define NONAME
  65. namespace rtc {
  66. namespace detail {
  67. // This is needed because the template parameters in Bind can't be resolved
  68. // if they're used both as parameters of the function pointer type and as
  69. // parameters to Bind itself: the function pointer parameters are exact
  70. // matches to the function prototype, but the parameters to bind have
  71. // references stripped. This trick allows the compiler to dictate the Bind
  72. // parameter types rather than deduce them.
  73. template <class T>
  74. struct identity {
  75. 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. // Define types such that sizeof(Yes) != sizeof(No).
  85. struct Yes {
  86. char dummy[1];
  87. };
  88. struct No {
  89. char dummy[2];
  90. };
  91. // Define two overloaded template functions with return types of different
  92. // size. This way, we can use sizeof() on the return type to determine which
  93. // function the compiler would have chosen. One function will be preferred
  94. // over the other if it is possible to create it without compiler errors,
  95. // otherwise the compiler will simply remove it, and default to the less
  96. // preferred function.
  97. template <typename R>
  98. static Yes test(R* r, decltype(r->AddRef(), r->Release(), 42));
  99. template <typename C>
  100. static No test(...);
  101. public:
  102. // Trick the compiler to tell if it's possible to call AddRef() and Release().
  103. static const bool value = sizeof(test<T>((T*)nullptr, 42)) == sizeof(Yes);
  104. };
  105. // TernaryTypeOperator is a helper class to select a type based on a static bool
  106. // value.
  107. template <bool condition, typename IfTrueT, typename IfFalseT>
  108. struct TernaryTypeOperator {};
  109. template <typename IfTrueT, typename IfFalseT>
  110. struct TernaryTypeOperator<true, IfTrueT, IfFalseT> {
  111. typedef IfTrueT type;
  112. };
  113. template <typename IfTrueT, typename IfFalseT>
  114. struct TernaryTypeOperator<false, IfTrueT, IfFalseT> {
  115. typedef IfFalseT type;
  116. };
  117. // PointerType<T>::type will be scoped_refptr<T> for ref counted types, and T*
  118. // otherwise.
  119. template <class T>
  120. struct PointerType {
  121. typedef typename TernaryTypeOperator<IsRefCounted<T>::value,
  122. scoped_refptr<T>,
  123. T*>::type type;
  124. };
  125. template <typename T>
  126. class UnretainedWrapper {
  127. public:
  128. explicit UnretainedWrapper(T* o) : ptr_(o) {}
  129. T* get() const { return ptr_; }
  130. private:
  131. T* ptr_;
  132. };
  133. } // namespace detail
  134. template <typename T>
  135. static inline detail::UnretainedWrapper<T> Unretained(T* o) {
  136. return detail::UnretainedWrapper<T>(o);
  137. }
  138. template <class ObjectT, class MethodT, class R, typename... Args>
  139. class MethodFunctor {
  140. public:
  141. MethodFunctor(MethodT method, ObjectT* object, Args... args)
  142. : method_(method), object_(object), args_(args...) {}
  143. R operator()() const {
  144. return CallMethod(std::index_sequence_for<Args...>());
  145. }
  146. private:
  147. template <size_t... S>
  148. R CallMethod(std::index_sequence<S...>) const {
  149. return (object_->*method_)(std::get<S>(args_)...);
  150. }
  151. MethodT method_;
  152. typename detail::PointerType<ObjectT>::type object_;
  153. typename std::tuple<typename std::remove_reference<Args>::type...> args_;
  154. };
  155. template <class ObjectT, class MethodT, class R, typename... Args>
  156. class UnretainedMethodFunctor {
  157. public:
  158. UnretainedMethodFunctor(MethodT method,
  159. detail::UnretainedWrapper<ObjectT> object,
  160. Args... args)
  161. : method_(method), object_(object.get()), args_(args...) {}
  162. R operator()() const {
  163. return CallMethod(std::index_sequence_for<Args...>());
  164. }
  165. private:
  166. template <size_t... S>
  167. R CallMethod(std::index_sequence<S...>) const {
  168. return (object_->*method_)(std::get<S>(args_)...);
  169. }
  170. MethodT method_;
  171. ObjectT* object_;
  172. typename std::tuple<typename std::remove_reference<Args>::type...> args_;
  173. };
  174. template <class FunctorT, class R, typename... Args>
  175. class Functor {
  176. public:
  177. Functor(const FunctorT& functor, Args... args)
  178. : functor_(functor), args_(args...) {}
  179. R operator()() const {
  180. return CallFunction(std::index_sequence_for<Args...>());
  181. }
  182. private:
  183. template <size_t... S>
  184. R CallFunction(std::index_sequence<S...>) const {
  185. return functor_(std::get<S>(args_)...);
  186. }
  187. FunctorT functor_;
  188. typename std::tuple<typename std::remove_reference<Args>::type...> args_;
  189. };
  190. #define FP_T(x) R (ObjectT::*x)(Args...)
  191. template <class ObjectT, class R, typename... Args>
  192. MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
  193. FP_T(method),
  194. ObjectT* object,
  195. typename detail::identity<Args>::type... args) {
  196. return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object,
  197. args...);
  198. }
  199. template <class ObjectT, class R, typename... Args>
  200. MethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
  201. FP_T(method),
  202. const scoped_refptr<ObjectT>& object,
  203. typename detail::identity<Args>::type... args) {
  204. return MethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(method, object.get(),
  205. args...);
  206. }
  207. template <class ObjectT, class R, typename... Args>
  208. UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...> Bind(
  209. FP_T(method),
  210. detail::UnretainedWrapper<ObjectT> object,
  211. typename detail::identity<Args>::type... args) {
  212. return UnretainedMethodFunctor<ObjectT, FP_T(NONAME), R, Args...>(
  213. method, object, args...);
  214. }
  215. #undef FP_T
  216. #define FP_T(x) R (ObjectT::*x)(Args...) const
  217. template <class ObjectT, class R, typename... Args>
  218. MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind(
  219. FP_T(method),
  220. const ObjectT* object,
  221. typename detail::identity<Args>::type... args) {
  222. return MethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(method, object,
  223. args...);
  224. }
  225. template <class ObjectT, class R, typename... Args>
  226. UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...> Bind(
  227. FP_T(method),
  228. detail::UnretainedWrapper<const ObjectT> object,
  229. typename detail::identity<Args>::type... args) {
  230. return UnretainedMethodFunctor<const ObjectT, FP_T(NONAME), R, Args...>(
  231. method, object, args...);
  232. }
  233. #undef FP_T
  234. #define FP_T(x) R (*x)(Args...)
  235. template <class R, typename... Args>
  236. Functor<FP_T(NONAME), R, Args...> Bind(
  237. FP_T(function),
  238. typename detail::identity<Args>::type... args) {
  239. return Functor<FP_T(NONAME), R, Args...>(function, args...);
  240. }
  241. #undef FP_T
  242. } // namespace rtc
  243. #undef NONAME
  244. #endif // RTC_BASE_BIND_H_