blob: 70738424699eaf9f5466ae98e449872ff9a22323 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
2 * libjingle
3 * Copyright 2013, Google Inc.
4 *
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
55#ifndef TALK_APP_WEBRTC_PROXY_H_
56#define TALK_APP_WEBRTC_PROXY_H_
57
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);
122 e_->Wait(rtc::kForever);
123 }
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
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000315#define BEGIN_PROXY_MAP(c) \
316 class c##Proxy : public c##Interface {\
317 protected:\
318 typedef c##Interface C;\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000319 c##Proxy(rtc::Thread* thread, C* c)\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000320 : owner_thread_(thread), \
321 c_(c) {}\
322 ~c##Proxy() {\
323 MethodCall0<c##Proxy, void> call(this, &c##Proxy::Release_s);\
324 call.Marshal(owner_thread_);\
325 }\
326 public:\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000327 static rtc::scoped_refptr<C> Create(rtc::Thread* thread, \
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000328 C* c) {\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000329 return new rtc::RefCountedObject<c##Proxy>(thread, c);\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000330 }\
331
332#define PROXY_METHOD0(r, method)\
333 r method() OVERRIDE {\
334 MethodCall0<C, r> call(c_.get(), &C::method);\
335 return call.Marshal(owner_thread_);\
336 }\
337
338#define PROXY_CONSTMETHOD0(r, method)\
339 r method() const OVERRIDE {\
340 ConstMethodCall0<C, r> call(c_.get(), &C::method);\
341 return call.Marshal(owner_thread_);\
342 }\
343
344#define PROXY_METHOD1(r, method, t1)\
345 r method(t1 a1) OVERRIDE {\
346 MethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
347 return call.Marshal(owner_thread_);\
348 }\
349
350#define PROXY_CONSTMETHOD1(r, method, t1)\
351 r method(t1 a1) const OVERRIDE {\
352 ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
353 return call.Marshal(owner_thread_);\
354 }\
355
356#define PROXY_METHOD2(r, method, t1, t2)\
357 r method(t1 a1, t2 a2) OVERRIDE {\
358 MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2);\
359 return call.Marshal(owner_thread_);\
360 }\
361
362#define PROXY_METHOD3(r, method, t1, t2, t3)\
363 r method(t1 a1, t2 a2, t3 a3) OVERRIDE {\
364 MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, a1, a2, a3);\
365 return call.Marshal(owner_thread_);\
366 }\
367
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000368#define PROXY_METHOD4(r, method, t1, t2, t3, t4)\
369 r method(t1 a1, t2 a2, t3 a3, t4 a4) OVERRIDE {\
370 MethodCall4<C, r, t1, t2, t3, t4> call(\
371 c_.get(), &C::method, a1, a2, a3, a4);\
372 return call.Marshal(owner_thread_);\
373 }\
374
375#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5)\
376 r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) OVERRIDE {\
377 MethodCall5<C, r, t1, t2, t3, t4, t5> call(\
378 c_.get(), &C::method, a1, a2, a3, a4, a5);\
379 return call.Marshal(owner_thread_);\
380 }\
381
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000382#define END_PROXY() \
383 private:\
384 void Release_s() {\
385 c_ = NULL;\
386 }\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000387 mutable rtc::Thread* owner_thread_;\
388 rtc::scoped_refptr<C> c_;\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000389 };\
390
391} // namespace webrtc
392
393#endif // TALK_APP_WEBRTC_PROXY_H_