blob: 134f58001f195ea48c41371d7549c39c9cefb3f3 [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); }
74
75 R value() { return r_; }
76
77 private:
78 R r_;
79};
80
81template <>
82class ReturnType<void> {
83 public:
84 template<typename C, typename M>
85 void Invoke(C* c, M m) { (c->*m)(); }
86 template<typename C, typename M, typename T1>
87 void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); }
88 template<typename C, typename M, typename T1, typename T2>
89 void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); }
90 template<typename C, typename M, typename T1, typename T2, typename T3>
91 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); }
92
93 void value() {}
94};
95
tommi@webrtc.org18de6f92014-11-04 12:08:48 +000096namespace internal {
97
98class SynchronousMethodCall
99 : public rtc::MessageData,
100 public rtc::MessageHandler {
101 public:
102 SynchronousMethodCall(rtc::MessageHandler* proxy)
103 : e_(), proxy_(proxy) {}
104 ~SynchronousMethodCall() {}
105
106 void Invoke(rtc::Thread* t) {
107 if (t->IsCurrent()) {
108 proxy_->OnMessage(NULL);
109 } else {
110 e_.reset(new rtc::Event(false, false));
111 t->Post(this, 0);
112 e_->Wait(rtc::kForever);
113 }
114 }
115
116 private:
117 void OnMessage(rtc::Message*) { proxy_->OnMessage(NULL); e_->Set(); }
118 rtc::scoped_ptr<rtc::Event> e_;
119 rtc::MessageHandler* proxy_;
120};
121
122} // internal
123
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000124template <typename C, typename R>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000125class MethodCall0 : public rtc::Message,
126 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000127 public:
128 typedef R (C::*Method)();
129 MethodCall0(C* c, Method m) : c_(c), m_(m) {}
130
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000131 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000132 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000133 return r_.value();
134 }
135
136 private:
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000137 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000138
139 C* c_;
140 Method m_;
141 ReturnType<R> r_;
142};
143
144template <typename C, typename R>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000145class ConstMethodCall0 : public rtc::Message,
146 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000147 public:
148 typedef R (C::*Method)() const;
149 ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
150
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000151 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000152 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000153 return r_.value();
154 }
155
156 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000157 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000158
159 C* c_;
160 Method m_;
161 ReturnType<R> r_;
162};
163
164template <typename C, typename R, typename T1>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000165class MethodCall1 : public rtc::Message,
166 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000167 public:
168 typedef R (C::*Method)(T1 a1);
169 MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
170
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000171 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000172 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000173 return r_.value();
174 }
175
176 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000177 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000178
179 C* c_;
180 Method m_;
181 ReturnType<R> r_;
182 T1 a1_;
183};
184
185template <typename C, typename R, typename T1>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000186class ConstMethodCall1 : public rtc::Message,
187 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000188 public:
189 typedef R (C::*Method)(T1 a1) const;
190 ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
191
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000192 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000193 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000194 return r_.value();
195 }
196
197 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000198 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000199
200 C* c_;
201 Method m_;
202 ReturnType<R> r_;
203 T1 a1_;
204};
205
206template <typename C, typename R, typename T1, typename T2>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000207class MethodCall2 : public rtc::Message,
208 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000209 public:
210 typedef R (C::*Method)(T1 a1, T2 a2);
211 MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {}
212
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000213 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000214 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000215 return r_.value();
216 }
217
218 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000219 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000220
221 C* c_;
222 Method m_;
223 ReturnType<R> r_;
224 T1 a1_;
225 T2 a2_;
226};
227
228template <typename C, typename R, typename T1, typename T2, typename T3>
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000229class MethodCall3 : public rtc::Message,
230 public rtc::MessageHandler {
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000231 public:
232 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3);
233 MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3)
234 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {}
235
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000236 R Marshal(rtc::Thread* t) {
tommi@webrtc.org18de6f92014-11-04 12:08:48 +0000237 internal::SynchronousMethodCall(this).Invoke(t);
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000238 return r_.value();
239 }
240
241 private:
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000242 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000243
244 C* c_;
245 Method m_;
246 ReturnType<R> r_;
247 T1 a1_;
248 T2 a2_;
249 T3 a3_;
250};
251
252#define BEGIN_PROXY_MAP(c) \
253 class c##Proxy : public c##Interface {\
254 protected:\
255 typedef c##Interface C;\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000256 c##Proxy(rtc::Thread* thread, C* c)\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000257 : owner_thread_(thread), \
258 c_(c) {}\
259 ~c##Proxy() {\
260 MethodCall0<c##Proxy, void> call(this, &c##Proxy::Release_s);\
261 call.Marshal(owner_thread_);\
262 }\
263 public:\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000264 static rtc::scoped_refptr<C> Create(rtc::Thread* thread, \
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000265 C* c) {\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000266 return new rtc::RefCountedObject<c##Proxy>(thread, c);\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000267 }\
268
269#define PROXY_METHOD0(r, method)\
270 r method() OVERRIDE {\
271 MethodCall0<C, r> call(c_.get(), &C::method);\
272 return call.Marshal(owner_thread_);\
273 }\
274
275#define PROXY_CONSTMETHOD0(r, method)\
276 r method() const OVERRIDE {\
277 ConstMethodCall0<C, r> call(c_.get(), &C::method);\
278 return call.Marshal(owner_thread_);\
279 }\
280
281#define PROXY_METHOD1(r, method, t1)\
282 r method(t1 a1) OVERRIDE {\
283 MethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
284 return call.Marshal(owner_thread_);\
285 }\
286
287#define PROXY_CONSTMETHOD1(r, method, t1)\
288 r method(t1 a1) const OVERRIDE {\
289 ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
290 return call.Marshal(owner_thread_);\
291 }\
292
293#define PROXY_METHOD2(r, method, t1, t2)\
294 r method(t1 a1, t2 a2) OVERRIDE {\
295 MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2);\
296 return call.Marshal(owner_thread_);\
297 }\
298
299#define PROXY_METHOD3(r, method, t1, t2, t3)\
300 r method(t1 a1, t2 a2, t3 a3) OVERRIDE {\
301 MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, a1, a2, a3);\
302 return call.Marshal(owner_thread_);\
303 }\
304
305#define END_PROXY() \
306 private:\
307 void Release_s() {\
308 c_ = NULL;\
309 }\
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +0000310 mutable rtc::Thread* owner_thread_;\
311 rtc::scoped_refptr<C> c_;\
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000312 };\
313
314} // namespace webrtc
315
316#endif // TALK_APP_WEBRTC_PROXY_H_