proxy.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412
  1. /*
  2. * Copyright 2013 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. // This file contains Macros for creating proxies for webrtc MediaStream and
  11. // PeerConnection classes.
  12. // TODO(deadbeef): Move this to pc/; this is part of the implementation.
  13. //
  14. // Example usage:
  15. //
  16. // class TestInterface : public rtc::RefCountInterface {
  17. // public:
  18. // std::string FooA() = 0;
  19. // std::string FooB(bool arg1) const = 0;
  20. // std::string FooC(bool arg1) = 0;
  21. // };
  22. //
  23. // Note that return types can not be a const reference.
  24. //
  25. // class Test : public TestInterface {
  26. // ... implementation of the interface.
  27. // };
  28. //
  29. // BEGIN_PROXY_MAP(Test)
  30. // PROXY_SIGNALING_THREAD_DESTRUCTOR()
  31. // PROXY_METHOD0(std::string, FooA)
  32. // PROXY_CONSTMETHOD1(std::string, FooB, arg1)
  33. // PROXY_WORKER_METHOD1(std::string, FooC, arg1)
  34. // END_PROXY_MAP()
  35. //
  36. // Where the destructor and first two methods are invoked on the signaling
  37. // thread, and the third is invoked on the worker thread.
  38. //
  39. // The proxy can be created using
  40. //
  41. // TestProxy::Create(Thread* signaling_thread, Thread* worker_thread,
  42. // TestInterface*).
  43. //
  44. // The variant defined with BEGIN_SIGNALING_PROXY_MAP is unaware of
  45. // the worker thread, and invokes all methods on the signaling thread.
  46. //
  47. // The variant defined with BEGIN_OWNED_PROXY_MAP does not use
  48. // refcounting, and instead just takes ownership of the object being proxied.
  49. #ifndef API_PROXY_H_
  50. #define API_PROXY_H_
  51. #include <memory>
  52. #include <string>
  53. #include <tuple>
  54. #include <type_traits>
  55. #include <utility>
  56. #include "api/scoped_refptr.h"
  57. #include "rtc_base/event.h"
  58. #include "rtc_base/message_handler.h"
  59. #include "rtc_base/ref_counted_object.h"
  60. #include "rtc_base/system/rtc_export.h"
  61. #include "rtc_base/thread.h"
  62. namespace rtc {
  63. class Location;
  64. }
  65. namespace webrtc {
  66. template <typename R>
  67. class ReturnType {
  68. public:
  69. template <typename C, typename M, typename... Args>
  70. void Invoke(C* c, M m, Args&&... args) {
  71. r_ = (c->*m)(std::forward<Args>(args)...);
  72. }
  73. R moved_result() { return std::move(r_); }
  74. private:
  75. R r_;
  76. };
  77. template <>
  78. class ReturnType<void> {
  79. public:
  80. template <typename C, typename M, typename... Args>
  81. void Invoke(C* c, M m, Args&&... args) {
  82. (c->*m)(std::forward<Args>(args)...);
  83. }
  84. void moved_result() {}
  85. };
  86. namespace internal {
  87. class RTC_EXPORT SynchronousMethodCall : public rtc::MessageData,
  88. public rtc::MessageHandler {
  89. public:
  90. explicit SynchronousMethodCall(rtc::MessageHandler* proxy);
  91. ~SynchronousMethodCall() override;
  92. void Invoke(const rtc::Location& posted_from, rtc::Thread* t);
  93. private:
  94. void OnMessage(rtc::Message*) override;
  95. rtc::Event e_;
  96. rtc::MessageHandler* proxy_;
  97. };
  98. } // namespace internal
  99. template <typename C, typename R, typename... Args>
  100. class MethodCall : public rtc::Message, public rtc::MessageHandler {
  101. public:
  102. typedef R (C::*Method)(Args...);
  103. MethodCall(C* c, Method m, Args&&... args)
  104. : c_(c),
  105. m_(m),
  106. args_(std::forward_as_tuple(std::forward<Args>(args)...)) {}
  107. R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
  108. internal::SynchronousMethodCall(this).Invoke(posted_from, t);
  109. return r_.moved_result();
  110. }
  111. private:
  112. void OnMessage(rtc::Message*) { Invoke(std::index_sequence_for<Args...>()); }
  113. template <size_t... Is>
  114. void Invoke(std::index_sequence<Is...>) {
  115. r_.Invoke(c_, m_, std::move(std::get<Is>(args_))...);
  116. }
  117. C* c_;
  118. Method m_;
  119. ReturnType<R> r_;
  120. std::tuple<Args&&...> args_;
  121. };
  122. template <typename C, typename R, typename... Args>
  123. class ConstMethodCall : public rtc::Message, public rtc::MessageHandler {
  124. public:
  125. typedef R (C::*Method)(Args...) const;
  126. ConstMethodCall(const C* c, Method m, Args&&... args)
  127. : c_(c),
  128. m_(m),
  129. args_(std::forward_as_tuple(std::forward<Args>(args)...)) {}
  130. R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
  131. internal::SynchronousMethodCall(this).Invoke(posted_from, t);
  132. return r_.moved_result();
  133. }
  134. private:
  135. void OnMessage(rtc::Message*) { Invoke(std::index_sequence_for<Args...>()); }
  136. template <size_t... Is>
  137. void Invoke(std::index_sequence<Is...>) {
  138. r_.Invoke(c_, m_, std::move(std::get<Is>(args_))...);
  139. }
  140. const C* c_;
  141. Method m_;
  142. ReturnType<R> r_;
  143. std::tuple<Args&&...> args_;
  144. };
  145. // Helper macros to reduce code duplication.
  146. #define PROXY_MAP_BOILERPLATE(c) \
  147. template <class INTERNAL_CLASS> \
  148. class c##ProxyWithInternal; \
  149. typedef c##ProxyWithInternal<c##Interface> c##Proxy; \
  150. template <class INTERNAL_CLASS> \
  151. class c##ProxyWithInternal : public c##Interface { \
  152. protected: \
  153. typedef c##Interface C; \
  154. \
  155. public: \
  156. const INTERNAL_CLASS* internal() const { return c_; } \
  157. INTERNAL_CLASS* internal() { return c_; }
  158. // clang-format off
  159. // clang-format would put the semicolon alone,
  160. // leading to a presubmit error (cpplint.py)
  161. #define END_PROXY_MAP() \
  162. };
  163. // clang-format on
  164. #define SIGNALING_PROXY_MAP_BOILERPLATE(c) \
  165. protected: \
  166. c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \
  167. : signaling_thread_(signaling_thread), c_(c) {} \
  168. \
  169. private: \
  170. mutable rtc::Thread* signaling_thread_;
  171. #define WORKER_PROXY_MAP_BOILERPLATE(c) \
  172. protected: \
  173. c##ProxyWithInternal(rtc::Thread* signaling_thread, \
  174. rtc::Thread* worker_thread, INTERNAL_CLASS* c) \
  175. : signaling_thread_(signaling_thread), \
  176. worker_thread_(worker_thread), \
  177. c_(c) {} \
  178. \
  179. private: \
  180. mutable rtc::Thread* signaling_thread_; \
  181. mutable rtc::Thread* worker_thread_;
  182. // Note that the destructor is protected so that the proxy can only be
  183. // destroyed via RefCountInterface.
  184. #define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
  185. protected: \
  186. ~c##ProxyWithInternal() { \
  187. MethodCall<c##ProxyWithInternal, void> call( \
  188. this, &c##ProxyWithInternal::DestroyInternal); \
  189. call.Marshal(RTC_FROM_HERE, destructor_thread()); \
  190. } \
  191. \
  192. private: \
  193. void DestroyInternal() { c_ = nullptr; } \
  194. rtc::scoped_refptr<INTERNAL_CLASS> c_;
  195. // Note: This doesn't use a unique_ptr, because it intends to handle a corner
  196. // case where an object's deletion triggers a callback that calls back into
  197. // this proxy object. If relying on a unique_ptr to delete the object, its
  198. // inner pointer would be set to null before this reentrant callback would have
  199. // a chance to run, resulting in a segfault.
  200. #define OWNED_PROXY_MAP_BOILERPLATE(c) \
  201. public: \
  202. ~c##ProxyWithInternal() { \
  203. MethodCall<c##ProxyWithInternal, void> call( \
  204. this, &c##ProxyWithInternal::DestroyInternal); \
  205. call.Marshal(RTC_FROM_HERE, destructor_thread()); \
  206. } \
  207. \
  208. private: \
  209. void DestroyInternal() { delete c_; } \
  210. INTERNAL_CLASS* c_;
  211. #define BEGIN_SIGNALING_PROXY_MAP(c) \
  212. PROXY_MAP_BOILERPLATE(c) \
  213. SIGNALING_PROXY_MAP_BOILERPLATE(c) \
  214. REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
  215. public: \
  216. static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
  217. rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \
  218. return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
  219. c); \
  220. }
  221. #define BEGIN_PROXY_MAP(c) \
  222. PROXY_MAP_BOILERPLATE(c) \
  223. WORKER_PROXY_MAP_BOILERPLATE(c) \
  224. REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
  225. public: \
  226. static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
  227. rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
  228. INTERNAL_CLASS* c) { \
  229. return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
  230. worker_thread, c); \
  231. }
  232. #define BEGIN_OWNED_PROXY_MAP(c) \
  233. PROXY_MAP_BOILERPLATE(c) \
  234. WORKER_PROXY_MAP_BOILERPLATE(c) \
  235. OWNED_PROXY_MAP_BOILERPLATE(c) \
  236. public: \
  237. static std::unique_ptr<c##Interface> Create( \
  238. rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
  239. std::unique_ptr<INTERNAL_CLASS> c) { \
  240. return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \
  241. signaling_thread, worker_thread, c.release())); \
  242. }
  243. #define PROXY_SIGNALING_THREAD_DESTRUCTOR() \
  244. private: \
  245. rtc::Thread* destructor_thread() const { return signaling_thread_; } \
  246. \
  247. public: // NOLINTNEXTLINE
  248. #define PROXY_WORKER_THREAD_DESTRUCTOR() \
  249. private: \
  250. rtc::Thread* destructor_thread() const { return worker_thread_; } \
  251. \
  252. public: // NOLINTNEXTLINE
  253. #define PROXY_METHOD0(r, method) \
  254. r method() override { \
  255. MethodCall<C, r> call(c_, &C::method); \
  256. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  257. }
  258. #define PROXY_CONSTMETHOD0(r, method) \
  259. r method() const override { \
  260. ConstMethodCall<C, r> call(c_, &C::method); \
  261. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  262. }
  263. #define PROXY_METHOD1(r, method, t1) \
  264. r method(t1 a1) override { \
  265. MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  266. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  267. }
  268. #define PROXY_CONSTMETHOD1(r, method, t1) \
  269. r method(t1 a1) const override { \
  270. ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  271. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  272. }
  273. #define PROXY_METHOD2(r, method, t1, t2) \
  274. r method(t1 a1, t2 a2) override { \
  275. MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
  276. std::move(a2)); \
  277. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  278. }
  279. #define PROXY_METHOD3(r, method, t1, t2, t3) \
  280. r method(t1 a1, t2 a2, t3 a3) override { \
  281. MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
  282. std::move(a2), std::move(a3)); \
  283. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  284. }
  285. #define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
  286. r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
  287. MethodCall<C, r, t1, t2, t3, t4> call(c_, &C::method, std::move(a1), \
  288. std::move(a2), std::move(a3), \
  289. std::move(a4)); \
  290. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  291. }
  292. #define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
  293. r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
  294. MethodCall<C, r, t1, t2, t3, t4, t5> call(c_, &C::method, std::move(a1), \
  295. std::move(a2), std::move(a3), \
  296. std::move(a4), std::move(a5)); \
  297. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  298. }
  299. // Define methods which should be invoked on the worker thread.
  300. #define PROXY_WORKER_METHOD0(r, method) \
  301. r method() override { \
  302. MethodCall<C, r> call(c_, &C::method); \
  303. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  304. }
  305. #define PROXY_WORKER_CONSTMETHOD0(r, method) \
  306. r method() const override { \
  307. ConstMethodCall<C, r> call(c_, &C::method); \
  308. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  309. }
  310. #define PROXY_WORKER_METHOD1(r, method, t1) \
  311. r method(t1 a1) override { \
  312. MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  313. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  314. }
  315. #define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \
  316. r method(t1 a1) const override { \
  317. ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  318. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  319. }
  320. #define PROXY_WORKER_METHOD2(r, method, t1, t2) \
  321. r method(t1 a1, t2 a2) override { \
  322. MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
  323. std::move(a2)); \
  324. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  325. }
  326. #define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \
  327. r method(t1 a1, t2 a2) const override { \
  328. ConstMethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
  329. std::move(a2)); \
  330. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  331. }
  332. #define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \
  333. r method(t1 a1, t2 a2, t3 a3) override { \
  334. MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
  335. std::move(a2), std::move(a3)); \
  336. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  337. }
  338. #define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \
  339. r method(t1 a1, t2 a2, t3 a3) const override { \
  340. ConstMethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
  341. std::move(a2), std::move(a3)); \
  342. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  343. }
  344. // For use when returning purely const state (set during construction).
  345. // Use with caution. This method should only be used when the return value will
  346. // always be the same.
  347. #define BYPASS_PROXY_CONSTMETHOD0(r, method) \
  348. r method() const override { \
  349. static_assert(!std::is_pointer<r>::value, "Type is a pointer"); \
  350. static_assert(!std::is_reference<r>::value, "Type is a reference"); \
  351. return c_->method(); \
  352. }
  353. } // namespace webrtc
  354. #endif // API_PROXY_H_