proxy.h 17 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417
  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 "api/task_queue/queued_task.h"
  58. #include "api/task_queue/task_queue_base.h"
  59. #include "rtc_base/event.h"
  60. #include "rtc_base/message_handler.h"
  61. #include "rtc_base/ref_counted_object.h"
  62. #include "rtc_base/system/rtc_export.h"
  63. #include "rtc_base/thread.h"
  64. namespace rtc {
  65. class Location;
  66. }
  67. namespace webrtc {
  68. template <typename R>
  69. class ReturnType {
  70. public:
  71. template <typename C, typename M, typename... Args>
  72. void Invoke(C* c, M m, Args&&... args) {
  73. r_ = (c->*m)(std::forward<Args>(args)...);
  74. }
  75. R moved_result() { return std::move(r_); }
  76. private:
  77. R r_;
  78. };
  79. template <>
  80. class ReturnType<void> {
  81. public:
  82. template <typename C, typename M, typename... Args>
  83. void Invoke(C* c, M m, Args&&... args) {
  84. (c->*m)(std::forward<Args>(args)...);
  85. }
  86. void moved_result() {}
  87. };
  88. template <typename C, typename R, typename... Args>
  89. class MethodCall : public QueuedTask {
  90. public:
  91. typedef R (C::*Method)(Args...);
  92. MethodCall(C* c, Method m, Args&&... args)
  93. : c_(c),
  94. m_(m),
  95. args_(std::forward_as_tuple(std::forward<Args>(args)...)) {}
  96. R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
  97. if (t->IsCurrent()) {
  98. Invoke(std::index_sequence_for<Args...>());
  99. } else {
  100. t->PostTask(std::unique_ptr<QueuedTask>(this));
  101. event_.Wait(rtc::Event::kForever);
  102. }
  103. return r_.moved_result();
  104. }
  105. private:
  106. bool Run() override {
  107. Invoke(std::index_sequence_for<Args...>());
  108. event_.Set();
  109. return false;
  110. }
  111. template <size_t... Is>
  112. void Invoke(std::index_sequence<Is...>) {
  113. r_.Invoke(c_, m_, std::move(std::get<Is>(args_))...);
  114. }
  115. C* c_;
  116. Method m_;
  117. ReturnType<R> r_;
  118. std::tuple<Args&&...> args_;
  119. rtc::Event event_;
  120. };
  121. template <typename C, typename R, typename... Args>
  122. class ConstMethodCall : public QueuedTask {
  123. public:
  124. typedef R (C::*Method)(Args...) const;
  125. ConstMethodCall(const C* c, Method m, Args&&... args)
  126. : c_(c),
  127. m_(m),
  128. args_(std::forward_as_tuple(std::forward<Args>(args)...)) {}
  129. R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
  130. if (t->IsCurrent()) {
  131. Invoke(std::index_sequence_for<Args...>());
  132. } else {
  133. t->PostTask(std::unique_ptr<QueuedTask>(this));
  134. event_.Wait(rtc::Event::kForever);
  135. }
  136. return r_.moved_result();
  137. }
  138. private:
  139. bool Run() override {
  140. Invoke(std::index_sequence_for<Args...>());
  141. event_.Set();
  142. return false;
  143. }
  144. template <size_t... Is>
  145. void Invoke(std::index_sequence<Is...>) {
  146. r_.Invoke(c_, m_, std::move(std::get<Is>(args_))...);
  147. }
  148. const C* c_;
  149. Method m_;
  150. ReturnType<R> r_;
  151. std::tuple<Args&&...> args_;
  152. rtc::Event event_;
  153. };
  154. // Helper macros to reduce code duplication.
  155. #define PROXY_MAP_BOILERPLATE(c) \
  156. template <class INTERNAL_CLASS> \
  157. class c##ProxyWithInternal; \
  158. typedef c##ProxyWithInternal<c##Interface> c##Proxy; \
  159. template <class INTERNAL_CLASS> \
  160. class c##ProxyWithInternal : public c##Interface { \
  161. protected: \
  162. typedef c##Interface C; \
  163. \
  164. public: \
  165. const INTERNAL_CLASS* internal() const { return c_; } \
  166. INTERNAL_CLASS* internal() { return c_; }
  167. // clang-format off
  168. // clang-format would put the semicolon alone,
  169. // leading to a presubmit error (cpplint.py)
  170. #define END_PROXY_MAP() \
  171. };
  172. // clang-format on
  173. #define SIGNALING_PROXY_MAP_BOILERPLATE(c) \
  174. protected: \
  175. c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \
  176. : signaling_thread_(signaling_thread), c_(c) {} \
  177. \
  178. private: \
  179. mutable rtc::Thread* signaling_thread_;
  180. #define WORKER_PROXY_MAP_BOILERPLATE(c) \
  181. protected: \
  182. c##ProxyWithInternal(rtc::Thread* signaling_thread, \
  183. rtc::Thread* worker_thread, INTERNAL_CLASS* c) \
  184. : signaling_thread_(signaling_thread), \
  185. worker_thread_(worker_thread), \
  186. c_(c) {} \
  187. \
  188. private: \
  189. mutable rtc::Thread* signaling_thread_; \
  190. mutable rtc::Thread* worker_thread_;
  191. // Note that the destructor is protected so that the proxy can only be
  192. // destroyed via RefCountInterface.
  193. #define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
  194. protected: \
  195. ~c##ProxyWithInternal() { \
  196. MethodCall<c##ProxyWithInternal, void> call( \
  197. this, &c##ProxyWithInternal::DestroyInternal); \
  198. call.Marshal(RTC_FROM_HERE, destructor_thread()); \
  199. } \
  200. \
  201. private: \
  202. void DestroyInternal() { c_ = nullptr; } \
  203. rtc::scoped_refptr<INTERNAL_CLASS> c_;
  204. // Note: This doesn't use a unique_ptr, because it intends to handle a corner
  205. // case where an object's deletion triggers a callback that calls back into
  206. // this proxy object. If relying on a unique_ptr to delete the object, its
  207. // inner pointer would be set to null before this reentrant callback would have
  208. // a chance to run, resulting in a segfault.
  209. #define OWNED_PROXY_MAP_BOILERPLATE(c) \
  210. public: \
  211. ~c##ProxyWithInternal() { \
  212. MethodCall<c##ProxyWithInternal, void> call( \
  213. this, &c##ProxyWithInternal::DestroyInternal); \
  214. call.Marshal(RTC_FROM_HERE, destructor_thread()); \
  215. } \
  216. \
  217. private: \
  218. void DestroyInternal() { delete c_; } \
  219. INTERNAL_CLASS* c_;
  220. #define BEGIN_SIGNALING_PROXY_MAP(c) \
  221. PROXY_MAP_BOILERPLATE(c) \
  222. SIGNALING_PROXY_MAP_BOILERPLATE(c) \
  223. REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
  224. public: \
  225. static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
  226. rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \
  227. return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
  228. c); \
  229. }
  230. #define BEGIN_PROXY_MAP(c) \
  231. PROXY_MAP_BOILERPLATE(c) \
  232. WORKER_PROXY_MAP_BOILERPLATE(c) \
  233. REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
  234. public: \
  235. static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
  236. rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
  237. INTERNAL_CLASS* c) { \
  238. return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
  239. worker_thread, c); \
  240. }
  241. #define BEGIN_OWNED_PROXY_MAP(c) \
  242. PROXY_MAP_BOILERPLATE(c) \
  243. WORKER_PROXY_MAP_BOILERPLATE(c) \
  244. OWNED_PROXY_MAP_BOILERPLATE(c) \
  245. public: \
  246. static std::unique_ptr<c##Interface> Create( \
  247. rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
  248. std::unique_ptr<INTERNAL_CLASS> c) { \
  249. return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \
  250. signaling_thread, worker_thread, c.release())); \
  251. }
  252. #define PROXY_SIGNALING_THREAD_DESTRUCTOR() \
  253. private: \
  254. rtc::Thread* destructor_thread() const { return signaling_thread_; } \
  255. \
  256. public: // NOLINTNEXTLINE
  257. #define PROXY_WORKER_THREAD_DESTRUCTOR() \
  258. private: \
  259. rtc::Thread* destructor_thread() const { return worker_thread_; } \
  260. \
  261. public: // NOLINTNEXTLINE
  262. #define PROXY_METHOD0(r, method) \
  263. r method() override { \
  264. MethodCall<C, r> call(c_, &C::method); \
  265. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  266. }
  267. #define PROXY_CONSTMETHOD0(r, method) \
  268. r method() const override { \
  269. ConstMethodCall<C, r> call(c_, &C::method); \
  270. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  271. }
  272. #define PROXY_METHOD1(r, method, t1) \
  273. r method(t1 a1) override { \
  274. MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  275. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  276. }
  277. #define PROXY_CONSTMETHOD1(r, method, t1) \
  278. r method(t1 a1) const override { \
  279. ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  280. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  281. }
  282. #define PROXY_METHOD2(r, method, t1, t2) \
  283. r method(t1 a1, t2 a2) override { \
  284. MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
  285. std::move(a2)); \
  286. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  287. }
  288. #define PROXY_METHOD3(r, method, t1, t2, t3) \
  289. r method(t1 a1, t2 a2, t3 a3) override { \
  290. MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
  291. std::move(a2), std::move(a3)); \
  292. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  293. }
  294. #define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
  295. r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
  296. MethodCall<C, r, t1, t2, t3, t4> call(c_, &C::method, std::move(a1), \
  297. std::move(a2), std::move(a3), \
  298. std::move(a4)); \
  299. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  300. }
  301. #define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
  302. r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
  303. MethodCall<C, r, t1, t2, t3, t4, t5> call(c_, &C::method, std::move(a1), \
  304. std::move(a2), std::move(a3), \
  305. std::move(a4), std::move(a5)); \
  306. return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
  307. }
  308. // Define methods which should be invoked on the worker thread.
  309. #define PROXY_WORKER_METHOD0(r, method) \
  310. r method() override { \
  311. MethodCall<C, r> call(c_, &C::method); \
  312. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  313. }
  314. #define PROXY_WORKER_CONSTMETHOD0(r, method) \
  315. r method() const override { \
  316. ConstMethodCall<C, r> call(c_, &C::method); \
  317. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  318. }
  319. #define PROXY_WORKER_METHOD1(r, method, t1) \
  320. r method(t1 a1) override { \
  321. MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  322. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  323. }
  324. #define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \
  325. r method(t1 a1) const override { \
  326. ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
  327. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  328. }
  329. #define PROXY_WORKER_METHOD2(r, method, t1, t2) \
  330. r method(t1 a1, t2 a2) override { \
  331. MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
  332. std::move(a2)); \
  333. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  334. }
  335. #define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \
  336. r method(t1 a1, t2 a2) const override { \
  337. ConstMethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
  338. std::move(a2)); \
  339. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  340. }
  341. #define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \
  342. r method(t1 a1, t2 a2, t3 a3) override { \
  343. MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
  344. std::move(a2), std::move(a3)); \
  345. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  346. }
  347. #define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \
  348. r method(t1 a1, t2 a2, t3 a3) const override { \
  349. ConstMethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
  350. std::move(a2), std::move(a3)); \
  351. return call.Marshal(RTC_FROM_HERE, worker_thread_); \
  352. }
  353. // For use when returning purely const state (set during construction).
  354. // Use with caution. This method should only be used when the return value will
  355. // always be the same.
  356. #define BYPASS_PROXY_CONSTMETHOD0(r, method) \
  357. r method() const override { \
  358. static_assert( \
  359. std::is_same<r, rtc::Thread*>::value || !std::is_pointer<r>::value, \
  360. "Type is a pointer"); \
  361. static_assert(!std::is_reference<r>::value, "Type is a reference"); \
  362. return c_->method(); \
  363. }
  364. } // namespace webrtc
  365. #endif // API_PROXY_H_