blob: 384e1897ef84286822ac5c8ae1686f3971a13c5a [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
jlmiller@webrtc.org5f93d0a2015-01-20 21:36:13 +00003 * Copyright 2013 Google Inc.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00004 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 *
8 * 1. Redistributions of source code must retain the above copyright notice,
9 * this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright notice,
11 * this list of conditions and the following disclaimer in the documentation
12 * and/or other materials provided with the distribution.
13 * 3. The name of the author may not be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR IMPLIED
17 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
18 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
19 * EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
20 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
21 * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS;
22 * OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
23 * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR
24 * OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
25 * ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28// This file contains Macros for creating proxies for webrtc MediaStream and
29// PeerConnection classes.
30
31//
32// Example usage:
33//
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000034// class TestInterface : public rtc::RefCountInterface {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000035// public:
36// std::string FooA() = 0;
37// std::string FooB(bool arg1) const = 0;
38// std::string FooC(bool arg1)= 0;
39// };
40//
41// Note that return types can not be a const reference.
42//
43// class Test : public TestInterface {
44// ... implementation of the interface.
45// };
46//
47// BEGIN_PROXY_MAP(Test)
48// PROXY_METHOD0(std::string, FooA)
49// PROXY_CONSTMETHOD1(std::string, FooB, arg1)
50// PROXY_METHOD1(std::string, FooC, arg1)
51// END_PROXY()
52//
53// The proxy can be created using TestProxy::Create(Thread*, TestInterface*).
54
Henrik Kjellander15583c12016-02-10 10:53:12 +010055#ifndef WEBRTC_API_PROXY_H_
56#define WEBRTC_API_PROXY_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000057
tommi@webrtc.org18de6f92014-11-04 12:08:48 +000058#include "webrtc/base/event.h"
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000059#include "webrtc/base/thread.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000060
61namespace webrtc {
62
63template <typename R>
64class ReturnType {
65 public:
66 template<typename C, typename M>
67 void Invoke(C* c, M m) { r_ = (c->*m)(); }
68 template<typename C, typename M, typename T1>
69 void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); }
70 template<typename C, typename M, typename T1, typename T2>
71 void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); }
72 template<typename C, typename M, typename T1, typename T2, typename T3>
73 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 +000074 template<typename C, typename M, typename T1, typename T2, typename T3,
75 typename T4>
76 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) {
77 r_ = (c->*m)(a1, a2, a3, a4);
78 }
79 template<typename C, typename M, typename T1, typename T2, typename T3,
80 typename T4, typename T5>
81 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) {
82 r_ = (c->*m)(a1, a2, a3, a4, a5);
83 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000084
85 R value() { return r_; }
86
87 private:
88 R r_;
89};
90
91template <>
92class ReturnType<void> {
93 public:
94 template<typename C, typename M>
95 void Invoke(C* c, M m) { (c->*m)(); }
96 template<typename C, typename M, typename T1>
97 void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); }
98 template<typename C, typename M, typename T1, typename T2>
99 void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); }
100 template<typename C, typename M, typename T1, typename T2, typename T3>
101 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); }
102
103 void value() {}
104};
105
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000106namespace internal {
107
108class SynchronousMethodCall
109 : public rtc::MessageData,
110 public rtc::MessageHandler {
111 public:
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000112 explicit SynchronousMethodCall(rtc::MessageHandler* proxy)
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000113 : e_(), proxy_(proxy) {}
114 ~SynchronousMethodCall() {}
115
116 void Invoke(rtc::Thread* t) {
117 if (t->IsCurrent()) {
118 proxy_->OnMessage(NULL);
119 } else {
120 e_.reset(new rtc::Event(false, false));
121 t->Post(this, 0);
andresp@webrtc.org53d90122015-02-09 14:19:09 +0000122 e_->Wait(rtc::Event::kForever);
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000123 }
124 }
125
126 private:
127 void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); }
128 rtc::scoped_ptr<rtc::Event> e_;
129 rtc::MessageHandler* proxy_;
130};
131
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000132} // namespace internal
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000133
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000134template <typename C, typename R>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000135class MethodCall0 : public rtc::Message,
136 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000137 public:
138 typedef R (C::*Method)();
139 MethodCall0(C* c, Method m) : c_(c), m_(m) {}
140
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000141 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000142 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000143 return r_.value();
144 }
145
146 private:
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000147 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000148
149 C* c_;
150 Method m_;
151 ReturnType<R> r_;
152};
153
154template <typename C, typename R>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000155class ConstMethodCall0 : public rtc::Message,
156 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000157 public:
158 typedef R (C::*Method)() const;
159 ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
160
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000161 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000162 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000163 return r_.value();
164 }
165
166 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000167 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000168
169 C* c_;
170 Method m_;
171 ReturnType<R> r_;
172};
173
174template <typename C, typename R, typename T1>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000175class MethodCall1 : public rtc::Message,
176 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000177 public:
178 typedef R (C::*Method)(T1 a1);
179 MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
180
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000181 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000182 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000183 return r_.value();
184 }
185
186 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000187 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188
189 C* c_;
190 Method m_;
191 ReturnType<R> r_;
192 T1 a1_;
193};
194
195template <typename C, typename R, typename T1>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000196class ConstMethodCall1 : public rtc::Message,
197 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000198 public:
199 typedef R (C::*Method)(T1 a1) const;
200 ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
201
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000202 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000203 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000204 return r_.value();
205 }
206
207 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000208 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000209
210 C* c_;
211 Method m_;
212 ReturnType<R> r_;
213 T1 a1_;
214};
215
216template <typename C, typename R, typename T1, typename T2>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000217class MethodCall2 : public rtc::Message,
218 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000219 public:
220 typedef R (C::*Method)(T1 a1, T2 a2);
221 MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {}
222
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000223 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000224 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000225 return r_.value();
226 }
227
228 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000229 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000230
231 C* c_;
232 Method m_;
233 ReturnType<R> r_;
234 T1 a1_;
235 T2 a2_;
236};
237
238template <typename C, typename R, typename T1, typename T2, typename T3>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000239class MethodCall3 : public rtc::Message,
240 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000241 public:
242 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3);
243 MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3)
244 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {}
245
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000246 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000247 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000248 return r_.value();
249 }
250
251 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000252 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000253
254 C* c_;
255 Method m_;
256 ReturnType<R> r_;
257 T1 a1_;
258 T2 a2_;
259 T3 a3_;
260};
261
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000262template <typename C, typename R, typename T1, typename T2, typename T3,
263 typename T4>
264class MethodCall4 : public rtc::Message,
265 public rtc::MessageHandler {
266 public:
267 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4);
268 MethodCall4(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4)
269 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {}
270
271 R Marshal(rtc::Thread* t) {
272 internal::SynchronousMethodCall(this).Invoke(t);
273 return r_.value();
274 }
275
276 private:
277 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_); }
278
279 C* c_;
280 Method m_;
281 ReturnType<R> r_;
282 T1 a1_;
283 T2 a2_;
284 T3 a3_;
285 T4 a4_;
286};
287
288template <typename C, typename R, typename T1, typename T2, typename T3,
289 typename T4, typename T5>
290class MethodCall5 : public rtc::Message,
291 public rtc::MessageHandler {
292 public:
293 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5);
294 MethodCall5(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5)
295 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {}
296
297 R Marshal(rtc::Thread* t) {
298 internal::SynchronousMethodCall(this).Invoke(t);
299 return r_.value();
300 }
301
302 private:
303 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_, a5_); }
304
305 C* c_;
306 Method m_;
307 ReturnType<R> r_;
308 T1 a1_;
309 T2 a2_;
310 T3 a3_;
311 T4 a4_;
312 T5 a5_;
313};
314
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000315#define BEGIN_PROXY_MAP(c) \
316 class c##Proxy : public c##Interface { \
317 protected: \
318 typedef c##Interface C; \
319 c##Proxy(rtc::Thread* thread, C* c) : owner_thread_(thread), c_(c) {} \
320 ~c##Proxy() { \
321 MethodCall0<c##Proxy, void> call(this, &c##Proxy::Release_s); \
322 call.Marshal(owner_thread_); \
323 } \
324 \
325 public: \
326 static rtc::scoped_refptr<C> Create(rtc::Thread* thread, C* c) { \
327 return new rtc::RefCountedObject<c##Proxy>(thread, c); \
328 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000329
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000330#define PROXY_METHOD0(r, method) \
331 r method() override { \
332 MethodCall0<C, r> call(c_.get(), &C::method); \
333 return call.Marshal(owner_thread_); \
334 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000335
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000336#define PROXY_CONSTMETHOD0(r, method) \
337 r method() const override { \
338 ConstMethodCall0<C, r> call(c_.get(), &C::method); \
339 return call.Marshal(owner_thread_); \
340 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000341
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000342#define PROXY_METHOD1(r, method, t1) \
343 r method(t1 a1) override { \
344 MethodCall1<C, r, t1> call(c_.get(), &C::method, a1); \
345 return call.Marshal(owner_thread_); \
346 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000347
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000348#define PROXY_CONSTMETHOD1(r, method, t1) \
349 r method(t1 a1) const override { \
350 ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, a1); \
351 return call.Marshal(owner_thread_); \
352 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000353
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000354#define PROXY_METHOD2(r, method, t1, t2) \
355 r method(t1 a1, t2 a2) override { \
356 MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2); \
357 return call.Marshal(owner_thread_); \
358 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000359
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000360#define PROXY_METHOD3(r, method, t1, t2, t3) \
361 r method(t1 a1, t2 a2, t3 a3) override { \
362 MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, a1, a2, a3); \
363 return call.Marshal(owner_thread_); \
364 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000365
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000366#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
367 r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
368 MethodCall4<C, r, t1, t2, t3, t4> call(c_.get(), &C::method, a1, a2, a3, \
369 a4); \
370 return call.Marshal(owner_thread_); \
371 }
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000372
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000373#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
374 r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
375 MethodCall5<C, r, t1, t2, t3, t4, t5> call(c_.get(), &C::method, a1, a2, \
376 a3, a4, a5); \
377 return call.Marshal(owner_thread_); \
378 }
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000379
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000380#define END_PROXY() \
381 private:\
382 void Release_s() {\
383 c_ = NULL;\
384 }\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000385 mutable rtc::Thread* owner_thread_;\
386 rtc::scoped_refptr<C> c_;\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000387 };\
388
389} // namespace webrtc
390
Henrik Kjellander15583c12016-02-10 10:53:12 +0100391#endif // WEBRTC_API_PROXY_H_