blob: 474b9a6d3b1c6c9319efaf5fdde41ed4b63ad632 [file] [log] [blame]
henrike@webrtc.org28e20752013-07-10 00:45:36 +00001/*
kjellanderb24317b2016-02-10 07:54:43 -08002 * Copyright 2013 The WebRTC project authors. All Rights Reserved.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00003 *
kjellanderb24317b2016-02-10 07:54:43 -08004 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
henrike@webrtc.org28e20752013-07-10 00:45:36 +00009 */
10
11// This file contains Macros for creating proxies for webrtc MediaStream and
12// PeerConnection classes.
deadbeefb10f32f2017-02-08 01:38:21 -080013// TODO(deadbeef): Move this to pc/; this is part of the implementation.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000014
15//
16// Example usage:
17//
buildbot@webrtc.orgd4e598d2014-07-29 17:36:52 +000018// class TestInterface : public rtc::RefCountInterface {
henrike@webrtc.org28e20752013-07-10 00:45:36 +000019// public:
20// std::string FooA() = 0;
21// std::string FooB(bool arg1) const = 0;
nisse72c8d2b2016-04-15 03:49:07 -070022// std::string FooC(bool arg1) = 0;
henrike@webrtc.org28e20752013-07-10 00:45:36 +000023// };
24//
25// Note that return types can not be a const reference.
26//
27// class Test : public TestInterface {
28// ... implementation of the interface.
29// };
30//
31// BEGIN_PROXY_MAP(Test)
deadbeefd99a2002017-01-18 08:55:23 -080032// PROXY_SIGNALING_THREAD_DESTRUCTOR()
henrike@webrtc.org28e20752013-07-10 00:45:36 +000033// PROXY_METHOD0(std::string, FooA)
34// PROXY_CONSTMETHOD1(std::string, FooB, arg1)
nisse72c8d2b2016-04-15 03:49:07 -070035// PROXY_WORKER_METHOD1(std::string, FooC, arg1)
deadbeefd99a2002017-01-18 08:55:23 -080036// END_PROXY_MAP()
henrike@webrtc.org28e20752013-07-10 00:45:36 +000037//
deadbeefd99a2002017-01-18 08:55:23 -080038// Where the destructor and first two methods are invoked on the signaling
39// thread, and the third is invoked on the worker thread.
nisse72c8d2b2016-04-15 03:49:07 -070040//
41// The proxy can be created using
42//
43// TestProxy::Create(Thread* signaling_thread, Thread* worker_thread,
44// TestInterface*).
45//
46// The variant defined with BEGIN_SIGNALING_PROXY_MAP is unaware of
47// the worker thread, and invokes all methods on the signaling thread.
deadbeefd99a2002017-01-18 08:55:23 -080048//
49// The variant defined with BEGIN_OWNED_PROXY_MAP does not use
50// refcounting, and instead just takes ownership of the object being proxied.
henrike@webrtc.org28e20752013-07-10 00:45:36 +000051
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020052#ifndef API_PROXY_H_
53#define API_PROXY_H_
henrike@webrtc.org28e20752013-07-10 00:45:36 +000054
kwibergd1fe2812016-04-27 06:47:29 -070055#include <memory>
Yves Gerey3e707812018-11-28 16:47:49 +010056#include <string>
Steve Antonc3639822019-11-26 15:27:50 -080057#include <tuple>
oprypin803dc292017-02-01 01:55:59 -080058#include <utility>
kwibergd1fe2812016-04-27 06:47:29 -070059
Mirko Bonadeid9708072019-01-25 20:26:48 +010060#include "api/scoped_refptr.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020061#include "rtc_base/event.h"
Steve Anton10542f22019-01-11 09:11:00 -080062#include "rtc_base/message_handler.h"
Steve Anton10542f22019-01-11 09:11:00 -080063#include "rtc_base/ref_counted_object.h"
Mirko Bonadei35214fc2019-09-23 14:54:28 +020064#include "rtc_base/system/rtc_export.h"
Mirko Bonadei92ea95e2017-09-15 06:47:31 +020065#include "rtc_base/thread.h"
henrike@webrtc.org28e20752013-07-10 00:45:36 +000066
Yves Gerey3e707812018-11-28 16:47:49 +010067namespace rtc {
68class Location;
69}
70
henrike@webrtc.org28e20752013-07-10 00:45:36 +000071namespace webrtc {
72
deadbeefd99a2002017-01-18 08:55:23 -080073// Helper macros to reduce code duplication.
deadbeefe814a0d2017-02-25 18:15:09 -080074#define PROXY_MAP_BOILERPLATE(c) \
75 template <class INTERNAL_CLASS> \
76 class c##ProxyWithInternal; \
77 typedef c##ProxyWithInternal<c##Interface> c##Proxy; \
78 template <class INTERNAL_CLASS> \
79 class c##ProxyWithInternal : public c##Interface { \
80 protected: \
81 typedef c##Interface C; \
82 \
83 public: \
84 const INTERNAL_CLASS* internal() const { return c_; } \
85 INTERNAL_CLASS* internal() { return c_; }
henrike@webrtc.org28e20752013-07-10 00:45:36 +000086
Yves Gerey665174f2018-06-19 15:03:05 +020087// clang-format off
88// clang-format would put the semicolon alone,
89// leading to a presubmit error (cpplint.py)
oprypin803dc292017-02-01 01:55:59 -080090#define END_PROXY_MAP() \
91 };
Yves Gerey665174f2018-06-19 15:03:05 +020092// clang-format on
oprypin803dc292017-02-01 01:55:59 -080093
deadbeefd99a2002017-01-18 08:55:23 -080094#define SIGNALING_PROXY_MAP_BOILERPLATE(c) \
95 protected: \
96 c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \
97 : signaling_thread_(signaling_thread), c_(c) {} \
98 \
99 private: \
100 mutable rtc::Thread* signaling_thread_;
101
102#define WORKER_PROXY_MAP_BOILERPLATE(c) \
103 protected: \
104 c##ProxyWithInternal(rtc::Thread* signaling_thread, \
105 rtc::Thread* worker_thread, INTERNAL_CLASS* c) \
106 : signaling_thread_(signaling_thread), \
107 worker_thread_(worker_thread), \
108 c_(c) {} \
109 \
110 private: \
111 mutable rtc::Thread* signaling_thread_; \
112 mutable rtc::Thread* worker_thread_;
113
114// Note that the destructor is protected so that the proxy can only be
115// destroyed via RefCountInterface.
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100116#define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
117 protected: \
118 ~c##ProxyWithInternal() { \
119 destructor_thread()->template Invoke<void>(RTC_FROM_HERE, \
120 [&] { c_ = nullptr; }); \
121 } \
122 \
123 private: \
deadbeefd99a2002017-01-18 08:55:23 -0800124 rtc::scoped_refptr<INTERNAL_CLASS> c_;
125
deadbeefe814a0d2017-02-25 18:15:09 -0800126// Note: This doesn't use a unique_ptr, because it intends to handle a corner
127// case where an object's deletion triggers a callback that calls back into
128// this proxy object. If relying on a unique_ptr to delete the object, its
129// inner pointer would be set to null before this reentrant callback would have
130// a chance to run, resulting in a segfault.
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100131#define OWNED_PROXY_MAP_BOILERPLATE(c) \
132 public: \
133 ~c##ProxyWithInternal() { \
134 destructor_thread()->template Invoke<void>(RTC_FROM_HERE, \
135 [&] { delete c_; }); \
136 } \
137 \
138 private: \
deadbeefe814a0d2017-02-25 18:15:09 -0800139 INTERNAL_CLASS* c_;
deadbeefd99a2002017-01-18 08:55:23 -0800140
141#define BEGIN_SIGNALING_PROXY_MAP(c) \
142 PROXY_MAP_BOILERPLATE(c) \
143 SIGNALING_PROXY_MAP_BOILERPLATE(c) \
144 REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
145 public: \
146 static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
147 rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \
148 return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
149 c); \
150 }
151
152#define BEGIN_PROXY_MAP(c) \
153 PROXY_MAP_BOILERPLATE(c) \
154 WORKER_PROXY_MAP_BOILERPLATE(c) \
155 REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
156 public: \
157 static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
158 rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
159 INTERNAL_CLASS* c) { \
160 return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
161 worker_thread, c); \
162 }
163
deadbeefe814a0d2017-02-25 18:15:09 -0800164#define BEGIN_OWNED_PROXY_MAP(c) \
165 PROXY_MAP_BOILERPLATE(c) \
166 WORKER_PROXY_MAP_BOILERPLATE(c) \
167 OWNED_PROXY_MAP_BOILERPLATE(c) \
168 public: \
169 static std::unique_ptr<c##Interface> Create( \
170 rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
171 std::unique_ptr<INTERNAL_CLASS> c) { \
172 return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \
173 signaling_thread, worker_thread, c.release())); \
deadbeefd99a2002017-01-18 08:55:23 -0800174 }
175
176#define PROXY_SIGNALING_THREAD_DESTRUCTOR() \
177 private: \
178 rtc::Thread* destructor_thread() const { return signaling_thread_; } \
179 \
oprypin803dc292017-02-01 01:55:59 -0800180 public: // NOLINTNEXTLINE
deadbeefd99a2002017-01-18 08:55:23 -0800181
182#define PROXY_WORKER_THREAD_DESTRUCTOR() \
183 private: \
184 rtc::Thread* destructor_thread() const { return worker_thread_; } \
185 \
oprypin803dc292017-02-01 01:55:59 -0800186 public: // NOLINTNEXTLINE
deadbeefd99a2002017-01-18 08:55:23 -0800187
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100188#define PROXY_METHOD0_BASE(t, modifier, r, method) \
189 r method() modifier override { \
190 return t->template Invoke<r>(RTC_FROM_HERE, [&] { return c_->method(); }); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000191 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000192
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100193#define PROXY_METHOD1_BASE(t, modifier, r, method, t1) \
194 r method(t1 a1) modifier override { \
195 return t->template Invoke<r>(RTC_FROM_HERE, \
196 [&] { return c_->method(std::move(a1)); }); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000197 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000198
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100199#define PROXY_METHOD2_BASE(t, modifier, r, method, t1, t2) \
200 r method(t1 a1, t2 a2) modifier override { \
201 return t->template Invoke<r>(RTC_FROM_HERE, [&] { \
202 return c_->method(std::move(a1), std::move(a2)); \
203 }); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000204 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000205
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100206#define PROXY_METHOD3_BASE(t, modifier, r, method, t1, t2, t3) \
207 r method(t1 a1, t2 a2, t3 a3) modifier override { \
208 return t->template Invoke<r>(RTC_FROM_HERE, [&] { \
209 return c_->method(std::move(a1), std::move(a2), std::move(a3)); \
210 }); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000211 }
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000212
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100213#define PROXY_METHOD4_BASE(t, modifier, r, method, t1, t2, t3, t4) \
214 r method(t1 a1, t2 a2, t3 a3, t4 a4) modifier override { \
215 return t->template Invoke<r>(RTC_FROM_HERE, [&] { \
216 return c_->method(std::move(a1), std::move(a2), std::move(a3), \
217 std::move(a4)); \
218 }); \
kjellander@webrtc.org14665ff2015-03-04 12:58:35 +0000219 }
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000220
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100221#define PROXY_METHOD5_BASE(t, modifier, r, method, t1, t2, t3, t4, t5) \
222 r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) modifier override { \
223 return t->template Invoke<r>(RTC_FROM_HERE, [&] { \
224 return c_->method(std::move(a1), std::move(a2), std::move(a3), \
225 std::move(a4), std::move(a5)); \
226 }); \
deadbeefd99a2002017-01-18 08:55:23 -0800227 }
228
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100229#define PROXY_METHOD0(r, method) \
230 PROXY_METHOD0_BASE(signaling_thread_, , r, method)
deadbeefd99a2002017-01-18 08:55:23 -0800231
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100232#define PROXY_CONSTMETHOD0(r, method) \
233 PROXY_METHOD0_BASE(signaling_thread_, const, r, method)
234
235#define PROXY_METHOD1(r, method, t1) \
236 PROXY_METHOD1_BASE(signaling_thread_, , r, method, t1)
237
238#define PROXY_CONSTMETHOD1(r, method, t1) \
239 PROXY_METHOD1_BASE(signaling_thread_, const, r, method, t1)
240
241#define PROXY_METHOD2(r, method, t1, t2) \
242 PROXY_METHOD2_BASE(signaling_thread_, , r, method, t1, t2)
243
244#define PROXY_METHOD3(r, method, t1, t2, t3) \
245 PROXY_METHOD3_BASE(signaling_thread_, , r, method, t1, t2, t3)
246
247#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
248 PROXY_METHOD4_BASE(signaling_thread_, , r, method, t1, t2, t3, t4)
249
250#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
251 PROXY_METHOD5_BASE(signaling_thread_, , r, method, t1, t2, t3, t4, t5)
nisse5b68ab52016-04-07 07:45:54 -0700252
253// Define methods which should be invoked on the worker thread.
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100254#define PROXY_WORKER_METHOD0(r, method) \
255 PROXY_METHOD0_BASE(worker_thread_, , r, method)
nisse5b68ab52016-04-07 07:45:54 -0700256
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100257#define PROXY_WORKER_CONSTMETHOD0(r, method) \
258 PROXY_METHOD0_BASE(worker_thread_, const, r, method)
perkj@webrtc.org81134d02015-01-12 08:30:16 +0000259
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100260#define PROXY_WORKER_METHOD1(r, method, t1) \
261 PROXY_METHOD1_BASE(worker_thread_, , r, method, t1)
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000262
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100263#define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \
264 PROXY_METHOD1_BASE(worker_thread_, const, r, method, t1)
deadbeefd99a2002017-01-18 08:55:23 -0800265
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100266#define PROXY_WORKER_METHOD2(r, method, t1, t2) \
267 PROXY_METHOD2_BASE(worker_thread_, , r, method, t1, t2)
deadbeefd99a2002017-01-18 08:55:23 -0800268
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100269#define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \
270 PROXY_METHOD2_BASE(worker_thread_, const, r, method, t1, t2)
deadbeefe814a0d2017-02-25 18:15:09 -0800271
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100272#define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \
273 PROXY_METHOD3_BASE(worker_thread_, , r, method, t1, t2, t3)
Steve Antonc3639822019-11-26 15:27:50 -0800274
Sebastian Janssonb0e07282020-01-10 19:39:58 +0100275#define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \
276 PROXY_METHOD3_BASE(worker_thread_, const, r, method, t1, t2, t3)
deadbeefd99a2002017-01-18 08:55:23 -0800277
henrike@webrtc.org28e20752013-07-10 00:45:36 +0000278} // namespace webrtc
279
Mirko Bonadei92ea95e2017-09-15 06:47:31 +0200280#endif // API_PROXY_H_