1 /* 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 rtc::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 "webrtc/base/event.h" 59 #include "webrtc/base/thread.h" 60 61 namespace webrtc { 62 63 template <typename R> 64 class 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 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 } 84 85 R value() { return r_; } 86 87 private: 88 R r_; 89 }; 90 91 template <> 92 class 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 106 namespace internal { 107 108 class SynchronousMethodCall 109 : public rtc::MessageData, 110 public rtc::MessageHandler { 111 public: 112 explicit SynchronousMethodCall(rtc::MessageHandler* proxy) 113 : 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::Event::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 132 } // namespace internal 133 134 template <typename C, typename R> 135 class MethodCall0 : public rtc::Message, 136 public rtc::MessageHandler { 137 public: 138 typedef R (C::*Method)(); 139 MethodCall0(C* c, Method m) : c_(c), m_(m) {} 140 141 R Marshal(rtc::Thread* t) { 142 internal::SynchronousMethodCall(this).Invoke(t); 143 return r_.value(); 144 } 145 146 private: 147 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); } 148 149 C* c_; 150 Method m_; 151 ReturnType<R> r_; 152 }; 153 154 template <typename C, typename R> 155 class ConstMethodCall0 : public rtc::Message, 156 public rtc::MessageHandler { 157 public: 158 typedef R (C::*Method)() const; 159 ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {} 160 161 R Marshal(rtc::Thread* t) { 162 internal::SynchronousMethodCall(this).Invoke(t); 163 return r_.value(); 164 } 165 166 private: 167 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_); } 168 169 C* c_; 170 Method m_; 171 ReturnType<R> r_; 172 }; 173 174 template <typename C, typename R, typename T1> 175 class MethodCall1 : public rtc::Message, 176 public rtc::MessageHandler { 177 public: 178 typedef R (C::*Method)(T1 a1); 179 MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} 180 181 R Marshal(rtc::Thread* t) { 182 internal::SynchronousMethodCall(this).Invoke(t); 183 return r_.value(); 184 } 185 186 private: 187 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); } 188 189 C* c_; 190 Method m_; 191 ReturnType<R> r_; 192 T1 a1_; 193 }; 194 195 template <typename C, typename R, typename T1> 196 class ConstMethodCall1 : public rtc::Message, 197 public rtc::MessageHandler { 198 public: 199 typedef R (C::*Method)(T1 a1) const; 200 ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} 201 202 R Marshal(rtc::Thread* t) { 203 internal::SynchronousMethodCall(this).Invoke(t); 204 return r_.value(); 205 } 206 207 private: 208 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); } 209 210 C* c_; 211 Method m_; 212 ReturnType<R> r_; 213 T1 a1_; 214 }; 215 216 template <typename C, typename R, typename T1, typename T2> 217 class MethodCall2 : public rtc::Message, 218 public rtc::MessageHandler { 219 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 223 R Marshal(rtc::Thread* t) { 224 internal::SynchronousMethodCall(this).Invoke(t); 225 return r_.value(); 226 } 227 228 private: 229 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_); } 230 231 C* c_; 232 Method m_; 233 ReturnType<R> r_; 234 T1 a1_; 235 T2 a2_; 236 }; 237 238 template <typename C, typename R, typename T1, typename T2, typename T3> 239 class MethodCall3 : public rtc::Message, 240 public rtc::MessageHandler { 241 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 246 R Marshal(rtc::Thread* t) { 247 internal::SynchronousMethodCall(this).Invoke(t); 248 return r_.value(); 249 } 250 251 private: 252 void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); } 253 254 C* c_; 255 Method m_; 256 ReturnType<R> r_; 257 T1 a1_; 258 T2 a2_; 259 T3 a3_; 260 }; 261 262 template <typename C, typename R, typename T1, typename T2, typename T3, 263 typename T4> 264 class 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 288 template <typename C, typename R, typename T1, typename T2, typename T3, 289 typename T4, typename T5> 290 class 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 315 #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 } 329 330 #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 } 335 336 #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 } 341 342 #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 } 347 348 #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 } 353 354 #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 } 359 360 #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 } 365 366 #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 } 372 373 #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 } 379 380 #define END_PROXY() \ 381 private:\ 382 void Release_s() {\ 383 c_ = NULL;\ 384 }\ 385 mutable rtc::Thread* owner_thread_;\ 386 rtc::scoped_refptr<C> c_;\ 387 };\ 388 389 } // namespace webrtc 390 391 #endif // TALK_APP_WEBRTC_PROXY_H_ 392