blob: 663e6c8873b0b1ee25b927de9a75ea6e8625f4c2 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2013 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
11// This file contains Macros for creating proxies for webrtc MediaStream and
12// PeerConnection classes.
13
14//
15// Example usage:
16//
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000017// class TestInterface : public rtc::RefCountInterface {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000018// public:
19// std::string FooA() = 0;
20// std::string FooB(bool arg1) const = 0;
nisse72c8d2b2016-04-15 03:49:07 -070021// std::string FooC(bool arg1) = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000022// };
23//
24// Note that return types can not be a const reference.
25//
26// class Test : public TestInterface {
27// ... implementation of the interface.
28// };
29//
30// BEGIN_PROXY_MAP(Test)
31// PROXY_METHOD0(std::string, FooA)
32// PROXY_CONSTMETHOD1(std::string, FooB, arg1)
nisse72c8d2b2016-04-15 03:49:07 -070033// PROXY_WORKER_METHOD1(std::string, FooC, arg1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +000034// END_PROXY()
35//
nisse72c8d2b2016-04-15 03:49:07 -070036// where the first two methods are invoked on the signaling thread,
37// 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.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000046
Henrik Kjellander15583c12016-02-10 10:53:12 +010047#ifndef WEBRTC_API_PROXY_H_
48#define WEBRTC_API_PROXY_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000049
tommi@webrtc.org18de6f92014-11-04 12:08:48 +000050#include "webrtc/base/event.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000051#include "webrtc/base/thread.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000052
53namespace webrtc {
54
55template <typename R>
56class ReturnType {
57 public:
58 template<typename C, typename M>
59 void Invoke(C* c, M m) { r_ = (c->*m)(); }
60 template<typename C, typename M, typename T1>
61 void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); }
62 template<typename C, typename M, typename T1, typename T2>
63 void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); }
64 template<typename C, typename M, typename T1, typename T2, typename T3>
65 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); }
perkj@webrtc.org81134d02015-01-12 08:30:16 +000066 template<typename C, typename M, typename T1, typename T2, typename T3,
67 typename T4>
68 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) {
69 r_ = (c->*m)(a1, a2, a3, a4);
70 }
71 template<typename C, typename M, typename T1, typename T2, typename T3,
72 typename T4, typename T5>
73 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
74 r_ = (c->*m)(a1, a2, a3, a4, a5);
75 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000076
77 R value() { return r_; }
78
79 private:
80 R r_;
81};
82
83template <>
84class ReturnType<void> {
85 public:
86 template<typename C, typename M>
87 void Invoke(C* c, M m) { (c->*m)(); }
88 template<typename C, typename M, typename T1>
89 void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); }
90 template<typename C, typename M, typename T1, typename T2>
91 void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); }
92 template<typename C, typename M, typename T1, typename T2, typename T3>
93 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); }
94
95 void value() {}
96};
97
tommi@webrtc.org18de6f92014-11-04 12:08:48 +000098namespace internal {
99
100class SynchronousMethodCall
101 : public rtc::MessageData,
102 public rtc::MessageHandler {
103 public:
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000104 explicit SynchronousMethodCall(rtc::MessageHandler* proxy)
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000105 : e_(), proxy_(proxy) {}
106 ~SynchronousMethodCall() {}
107
108 void Invoke(rtc::Thread* t) {
109 if (t->IsCurrent()) {
110 proxy_->OnMessage(NULL);
111 } else {
112 e_.reset(new rtc::Event(false, false));
113 t->Post(this, 0);
andresp@webrtc.org53d90122015-02-09 14:19:09 +0000114 e_->Wait(rtc::Event::kForever);
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000115 }
116 }
117
118 private:
119 void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); }
120 rtc::scoped_ptr<rtc::Event> e_;
121 rtc::MessageHandler* proxy_;
122};
123
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000124} // namespace internal
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000125
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000126template <typename C, typename R>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000127class MethodCall0 : public rtc::Message,
128 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000129 public:
130 typedef R (C::*Method)();
131 MethodCall0(C* c, Method m) : c_(c), m_(m) {}
132
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000133 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000134 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000135 return r_.value();
136 }
137
138 private:
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000139 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000140
141 C* c_;
142 Method m_;
143 ReturnType<R> r_;
144};
145
146template <typename C, typename R>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000147class ConstMethodCall0 : public rtc::Message,
148 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000149 public:
150 typedef R (C::*Method)() const;
151 ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
152
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000153 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000154 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000155 return r_.value();
156 }
157
158 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000159 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000160
161 C* c_;
162 Method m_;
163 ReturnType<R> r_;
164};
165
166template <typename C, typename R, typename T1>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000167class MethodCall1 : public rtc::Message,
168 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000169 public:
170 typedef R (C::*Method)(T1 a1);
171 MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
172
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000173 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000174 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000175 return r_.value();
176 }
177
178 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000179 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000180
181 C* c_;
182 Method m_;
183 ReturnType<R> r_;
184 T1 a1_;
185};
186
187template <typename C, typename R, typename T1>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000188class ConstMethodCall1 : public rtc::Message,
189 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000190 public:
191 typedef R (C::*Method)(T1 a1) const;
192 ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
193
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000194 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000195 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000196 return r_.value();
197 }
198
199 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000200 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000201
202 C* c_;
203 Method m_;
204 ReturnType<R> r_;
205 T1 a1_;
206};
207
208template <typename C, typename R, typename T1, typename T2>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000209class MethodCall2 : public rtc::Message,
210 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000211 public:
212 typedef R (C::*Method)(T1 a1, T2 a2);
213 MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {}
214
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000215 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000216 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000217 return r_.value();
218 }
219
220 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000221 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000222
223 C* c_;
224 Method m_;
225 ReturnType<R> r_;
226 T1 a1_;
227 T2 a2_;
228};
229
230template <typename C, typename R, typename T1, typename T2, typename T3>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000231class MethodCall3 : public rtc::Message,
232 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000233 public:
234 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3);
235 MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3)
236 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {}
237
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000238 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000239 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000240 return r_.value();
241 }
242
243 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000244 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000245
246 C* c_;
247 Method m_;
248 ReturnType<R> r_;
249 T1 a1_;
250 T2 a2_;
251 T3 a3_;
252};
253
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000254template <typename C, typename R, typename T1, typename T2, typename T3,
255 typename T4>
256class MethodCall4 : public rtc::Message,
257 public rtc::MessageHandler {
258 public:
259 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4);
260 MethodCall4(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4)
261 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {}
262
263 R Marshal(rtc::Thread* t) {
264 internal::SynchronousMethodCall(this).Invoke(t);
265 return r_.value();
266 }
267
268 private:
269 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_); }
270
271 C* c_;
272 Method m_;
273 ReturnType<R> r_;
274 T1 a1_;
275 T2 a2_;
276 T3 a3_;
277 T4 a4_;
278};
279
280template <typename C, typename R, typename T1, typename T2, typename T3,
281 typename T4, typename T5>
282class MethodCall5 : public rtc::Message,
283 public rtc::MessageHandler {
284 public:
285 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
286 MethodCall5(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
287 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {}
288
289 R Marshal(rtc::Thread* t) {
290 internal::SynchronousMethodCall(this).Invoke(t);
291 return r_.value();
292 }
293
294 private:
295 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_, a5_); }
296
297 C* c_;
298 Method m_;
299 ReturnType<R> r_;
300 T1 a1_;
301 T2 a2_;
302 T3 a3_;
303 T4 a4_;
304 T5 a5_;
305};
306
nisse72c8d2b2016-04-15 03:49:07 -0700307#define BEGIN_SIGNALING_PROXY_MAP(c) \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000308 class c##Proxy : public c##Interface { \
309 protected: \
310 typedef c##Interface C; \
nisse5b68ab52016-04-07 07:45:54 -0700311 c##Proxy(rtc::Thread* signaling_thread, C* c) \
312 : signaling_thread_(signaling_thread), c_(c) {} \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000313 ~c##Proxy() { \
nisse72c8d2b2016-04-15 03:49:07 -0700314 MethodCall0<c##Proxy, void> call( \
315 this, &c##Proxy::Release_s); \
nisse5b68ab52016-04-07 07:45:54 -0700316 call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000317 } \
318 \
319 public: \
nisse5b68ab52016-04-07 07:45:54 -0700320 static rtc::scoped_refptr<C> Create(rtc::Thread* signaling_thread, C* c) { \
nisse72c8d2b2016-04-15 03:49:07 -0700321 return new rtc::RefCountedObject<c##Proxy>( \
322 signaling_thread, c); \
nisse5b68ab52016-04-07 07:45:54 -0700323 }
324
nisse72c8d2b2016-04-15 03:49:07 -0700325#define BEGIN_PROXY_MAP(c) \
nisse5b68ab52016-04-07 07:45:54 -0700326 class c##Proxy : public c##Interface { \
327 protected: \
328 typedef c##Interface C; \
329 c##Proxy(rtc::Thread* signaling_thread, rtc::Thread* worker_thread, C* c) \
330 : signaling_thread_(signaling_thread), \
331 worker_thread_(worker_thread), \
332 c_(c) {} \
333 ~c##Proxy() { \
334 MethodCall0<c##Proxy, void> call(this, &c##Proxy::Release_s); \
335 call.Marshal(signaling_thread_); \
336 } \
337 \
338 public: \
339 static rtc::scoped_refptr<C> Create( \
340 rtc::Thread* signaling_thread, rtc::Thread* worker_thread, C* c) { \
341 return new rtc::RefCountedObject<c##Proxy>( \
342 signaling_thread, worker_thread, c); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000343 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000344
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000345#define PROXY_METHOD0(r, method) \
346 r method() override { \
347 MethodCall0<C, r> call(c_.get(), &C::method); \
nisse5b68ab52016-04-07 07:45:54 -0700348 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000349 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000350
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000351#define PROXY_CONSTMETHOD0(r, method) \
352 r method() const override { \
353 ConstMethodCall0<C, r> call(c_.get(), &C::method); \
nisse5b68ab52016-04-07 07:45:54 -0700354 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000355 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000356
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000357#define PROXY_METHOD1(r, method, t1) \
358 r method(t1 a1) override { \
359 MethodCall1<C, r, t1> call(c_.get(), &C::method, a1); \
nisse5b68ab52016-04-07 07:45:54 -0700360 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000361 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000362
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000363#define PROXY_CONSTMETHOD1(r, method, t1) \
364 r method(t1 a1) const override { \
365 ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, a1); \
nisse5b68ab52016-04-07 07:45:54 -0700366 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000367 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000368
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000369#define PROXY_METHOD2(r, method, t1, t2) \
370 r method(t1 a1, t2 a2) override { \
371 MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2); \
nisse5b68ab52016-04-07 07:45:54 -0700372 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000373 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000374
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000375#define PROXY_METHOD3(r, method, t1, t2, t3) \
376 r method(t1 a1, t2 a2, t3 a3) override { \
377 MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, a1, a2, a3); \
nisse5b68ab52016-04-07 07:45:54 -0700378 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000379 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000381#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
382 r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
383 MethodCall4<C, r, t1, t2, t3, t4> call(c_.get(), &C::method, a1, a2, a3, \
384 a4); \
nisse5b68ab52016-04-07 07:45:54 -0700385 return call.Marshal(signaling_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000386 }
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000387
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000388#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
389 r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
390 MethodCall5<C, r, t1, t2, t3, t4, t5> call(c_.get(), &C::method, a1, a2, \
391 a3, a4, a5); \
nisse5b68ab52016-04-07 07:45:54 -0700392 return call.Marshal(signaling_thread_); \
393 }
394
395// Define methods which should be invoked on the worker thread.
396#define PROXY_WORKER_METHOD1(r, method, t1) \
397 r method(t1 a1) override { \
398 MethodCall1<C, r, t1> call(c_.get(), &C::method, a1); \
399 return call.Marshal(worker_thread_); \
400 }
401
402#define PROXY_WORKER_METHOD2(r, method, t1, t2) \
403 r method(t1 a1, t2 a2) override { \
404 MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2); \
405 return call.Marshal(worker_thread_); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000406 }
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000407
nisse72c8d2b2016-04-15 03:49:07 -0700408#define END_SIGNALING_PROXY() \
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000409 private:\
410 void Release_s() {\
411 c_ = NULL;\
412 }\
nisse5b68ab52016-04-07 07:45:54 -0700413 mutable rtc::Thread* signaling_thread_;\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000414 rtc::scoped_refptr<C> c_;\
nisse72c8d2b2016-04-15 03:49:07 -0700415 };
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000416
nisse72c8d2b2016-04-15 03:49:07 -0700417#define END_PROXY() \
nisse5b68ab52016-04-07 07:45:54 -0700418 private: \
419 void Release_s() { \
420 c_ = NULL; \
421 } \
422 mutable rtc::Thread* signaling_thread_; \
423 mutable rtc::Thread* worker_thread_; \
424 rtc::scoped_refptr<C> c_; \
425 }; \
426
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000427} // namespace webrtc
428
Henrik Kjellander15583c12016-02-10 10:53:12 +0100429#endif // WEBRTC_API_PROXY_H_