blob: 4db4befa653c2f6f282d7976bffe63e3c0420786 [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//
34// class TestInterface : public talk_base::RefCountInterface {
35// 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
58#include "talk/base/thread.h"
59
60namespace webrtc {
61
62template <typename R>
63class ReturnType {
64 public:
65 template<typename C, typename M>
66 void Invoke(C* c, M m) { r_ = (c->*m)(); }
67 template<typename C, typename M, typename T1>
68 void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); }
69 template<typename C, typename M, typename T1, typename T2>
70 void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); }
71 template<typename C, typename M, typename T1, typename T2, typename T3>
72 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); }
73
74 R value() { return r_; }
75
76 private:
77 R r_;
78};
79
80template <>
81class ReturnType<void> {
82 public:
83 template<typename C, typename M>
84 void Invoke(C* c, M m) { (c->*m)(); }
85 template<typename C, typename M, typename T1>
86 void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); }
87 template<typename C, typename M, typename T1, typename T2>
88 void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); }
89 template<typename C, typename M, typename T1, typename T2, typename T3>
90 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); }
91
92 void value() {}
93};
94
95template <typename C, typename R>
96class MethodCall0 : public talk_base::Message,
97 public talk_base::MessageHandler {
98 public:
99 typedef R (C::*Method)();
100 MethodCall0(C* c, Method m) : c_(c), m_(m) {}
101
102 R Marshal(talk_base::Thread* t) {
103 t->Send(this, 0);
104 return r_.value();
105 }
106
107 private:
108 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_);}
109
110 C* c_;
111 Method m_;
112 ReturnType<R> r_;
113};
114
115template <typename C, typename R>
116class ConstMethodCall0 : public talk_base::Message,
117 public talk_base::MessageHandler {
118 public:
119 typedef R (C::*Method)() const;
120 ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {}
121
122 R Marshal(talk_base::Thread* t) {
123 t->Send(this, 0);
124 return r_.value();
125 }
126
127 private:
128 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_); }
129
130 C* c_;
131 Method m_;
132 ReturnType<R> r_;
133};
134
135template <typename C, typename R, typename T1>
136class MethodCall1 : public talk_base::Message,
137 public talk_base::MessageHandler {
138 public:
139 typedef R (C::*Method)(T1 a1);
140 MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
141
142 R Marshal(talk_base::Thread* t) {
143 t->Send(this, 0);
144 return r_.value();
145 }
146
147 private:
148 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_); }
149
150 C* c_;
151 Method m_;
152 ReturnType<R> r_;
153 T1 a1_;
154};
155
156template <typename C, typename R, typename T1>
157class ConstMethodCall1 : public talk_base::Message,
158 public talk_base::MessageHandler {
159 public:
160 typedef R (C::*Method)(T1 a1) const;
161 ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {}
162
163 R Marshal(talk_base::Thread* t) {
164 t->Send(this, 0);
165 return r_.value();
166 }
167
168 private:
169 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_); }
170
171 C* c_;
172 Method m_;
173 ReturnType<R> r_;
174 T1 a1_;
175};
176
177template <typename C, typename R, typename T1, typename T2>
178class MethodCall2 : public talk_base::Message,
179 public talk_base::MessageHandler {
180 public:
181 typedef R (C::*Method)(T1 a1, T2 a2);
182 MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {}
183
184 R Marshal(talk_base::Thread* t) {
185 t->Send(this, 0);
186 return r_.value();
187 }
188
189 private:
190 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_, a2_); }
191
192 C* c_;
193 Method m_;
194 ReturnType<R> r_;
195 T1 a1_;
196 T2 a2_;
197};
198
199template <typename C, typename R, typename T1, typename T2, typename T3>
200class MethodCall3 : public talk_base::Message,
201 public talk_base::MessageHandler {
202 public:
203 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3);
204 MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3)
205 : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {}
206
207 R Marshal(talk_base::Thread* t) {
208 t->Send(this, 0);
209 return r_.value();
210 }
211
212 private:
213 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); }
214
215 C* c_;
216 Method m_;
217 ReturnType<R> r_;
218 T1 a1_;
219 T2 a2_;
220 T3 a3_;
221};
222
223#define BEGIN_PROXY_MAP(c) \
224 class c##Proxy : public c##Interface {\
225 protected:\
226 typedef c##Interface C;\
227 c##Proxy(talk_base::Thread* thread, C* c)\
228 : owner_thread_(thread), \
229 c_(c) {}\
230 ~c##Proxy() {\
231 MethodCall0<c##Proxy, void> call(this, &c##Proxy::Release_s);\
232 call.Marshal(owner_thread_);\
233 }\
234 public:\
235 static talk_base::scoped_refptr<C> Create(talk_base::Thread* thread, \
236 C* c) {\
237 return new talk_base::RefCountedObject<c##Proxy>(thread, c);\
238 }\
239
240#define PROXY_METHOD0(r, method)\
241 r method() OVERRIDE {\
242 MethodCall0<C, r> call(c_.get(), &C::method);\
243 return call.Marshal(owner_thread_);\
244 }\
245
246#define PROXY_CONSTMETHOD0(r, method)\
247 r method() const OVERRIDE {\
248 ConstMethodCall0<C, r> call(c_.get(), &C::method);\
249 return call.Marshal(owner_thread_);\
250 }\
251
252#define PROXY_METHOD1(r, method, t1)\
253 r method(t1 a1) OVERRIDE {\
254 MethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
255 return call.Marshal(owner_thread_);\
256 }\
257
258#define PROXY_CONSTMETHOD1(r, method, t1)\
259 r method(t1 a1) const OVERRIDE {\
260 ConstMethodCall1<C, r, t1> call(c_.get(), &C::method, a1);\
261 return call.Marshal(owner_thread_);\
262 }\
263
264#define PROXY_METHOD2(r, method, t1, t2)\
265 r method(t1 a1, t2 a2) OVERRIDE {\
266 MethodCall2<C, r, t1, t2> call(c_.get(), &C::method, a1, a2);\
267 return call.Marshal(owner_thread_);\
268 }\
269
270#define PROXY_METHOD3(r, method, t1, t2, t3)\
271 r method(t1 a1, t2 a2, t3 a3) OVERRIDE {\
272 MethodCall3<C, r, t1, t2, t3> call(c_.get(), &C::method, a1, a2, a3);\
273 return call.Marshal(owner_thread_);\
274 }\
275
276#define END_PROXY() \
277 private:\
278 void Release_s() {\
279 c_ = NULL;\
280 }\
281 mutable talk_base::Thread* owner_thread_;\
282 talk_base::scoped_refptr<C> c_;\
283 };\
284
285} // namespace webrtc
286
287#endif // TALK_APP_WEBRTC_PROXY_H_