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 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 60 namespace webrtc { 61 62 template <typename R> 63 class ReturnType { 64 public: 65 template<typename C, typename M> Invoke(C * c,M m)66 void Invoke(C* c, M m) { r_ = (c->*m)(); } 67 template<typename C, typename M, typename T1> Invoke(C * c,M m,T1 a1)68 void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); } 69 template<typename C, typename M, typename T1, typename T2> Invoke(C * c,M m,T1 a1,T2 a2)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> Invoke(C * c,M m,T1 a1,T2 a2,T3 a3)72 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); } 73 value()74 R value() { return r_; } 75 76 private: 77 R r_; 78 }; 79 80 template <> 81 class ReturnType<void> { 82 public: 83 template<typename C, typename M> Invoke(C * c,M m)84 void Invoke(C* c, M m) { (c->*m)(); } 85 template<typename C, typename M, typename T1> Invoke(C * c,M m,T1 a1)86 void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); } 87 template<typename C, typename M, typename T1, typename T2> Invoke(C * c,M m,T1 a1,T2 a2)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> Invoke(C * c,M m,T1 a1,T2 a2,T3 a3)90 void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); } 91 value()92 void value() {} 93 }; 94 95 template <typename C, typename R> 96 class MethodCall0 : public talk_base::Message, 97 public talk_base::MessageHandler { 98 public: 99 typedef R (C::*Method)(); MethodCall0(C * c,Method m)100 MethodCall0(C* c, Method m) : c_(c), m_(m) {} 101 Marshal(talk_base::Thread * t)102 R Marshal(talk_base::Thread* t) { 103 t->Send(this, 0); 104 return r_.value(); 105 } 106 107 private: OnMessage(talk_base::Message *)108 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_);} 109 110 C* c_; 111 Method m_; 112 ReturnType<R> r_; 113 }; 114 115 template <typename C, typename R> 116 class ConstMethodCall0 : public talk_base::Message, 117 public talk_base::MessageHandler { 118 public: 119 typedef R (C::*Method)() const; ConstMethodCall0(C * c,Method m)120 ConstMethodCall0(C* c, Method m) : c_(c), m_(m) {} 121 Marshal(talk_base::Thread * t)122 R Marshal(talk_base::Thread* t) { 123 t->Send(this, 0); 124 return r_.value(); 125 } 126 127 private: OnMessage(talk_base::Message *)128 void OnMessage(talk_base::Message*) { r_.Invoke(c_, m_); } 129 130 C* c_; 131 Method m_; 132 ReturnType<R> r_; 133 }; 134 135 template <typename C, typename R, typename T1> 136 class MethodCall1 : public talk_base::Message, 137 public talk_base::MessageHandler { 138 public: 139 typedef R (C::*Method)(T1 a1); MethodCall1(C * c,Method m,T1 a1)140 MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} 141 Marshal(talk_base::Thread * t)142 R Marshal(talk_base::Thread* t) { 143 t->Send(this, 0); 144 return r_.value(); 145 } 146 147 private: OnMessage(talk_base::Message *)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 156 template <typename C, typename R, typename T1> 157 class ConstMethodCall1 : public talk_base::Message, 158 public talk_base::MessageHandler { 159 public: 160 typedef R (C::*Method)(T1 a1) const; ConstMethodCall1(C * c,Method m,T1 a1)161 ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} 162 Marshal(talk_base::Thread * t)163 R Marshal(talk_base::Thread* t) { 164 t->Send(this, 0); 165 return r_.value(); 166 } 167 168 private: OnMessage(talk_base::Message *)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 177 template <typename C, typename R, typename T1, typename T2> 178 class MethodCall2 : public talk_base::Message, 179 public talk_base::MessageHandler { 180 public: 181 typedef R (C::*Method)(T1 a1, T2 a2); MethodCall2(C * c,Method m,T1 a1,T2 a2)182 MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {} 183 Marshal(talk_base::Thread * t)184 R Marshal(talk_base::Thread* t) { 185 t->Send(this, 0); 186 return r_.value(); 187 } 188 189 private: OnMessage(talk_base::Message *)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 199 template <typename C, typename R, typename T1, typename T2, typename T3> 200 class MethodCall3 : public talk_base::Message, 201 public talk_base::MessageHandler { 202 public: 203 typedef R (C::*Method)(T1 a1, T2 a2, T3 a3); MethodCall3(C * c,Method m,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 Marshal(talk_base::Thread * t)207 R Marshal(talk_base::Thread* t) { 208 t->Send(this, 0); 209 return r_.value(); 210 } 211 212 private: OnMessage(talk_base::Message *)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_ 288