123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417 |
- #ifndef API_PROXY_H_
- #define API_PROXY_H_
- #include <memory>
- #include <string>
- #include <tuple>
- #include <type_traits>
- #include <utility>
- #include "api/scoped_refptr.h"
- #include "api/task_queue/queued_task.h"
- #include "api/task_queue/task_queue_base.h"
- #include "rtc_base/event.h"
- #include "rtc_base/message_handler.h"
- #include "rtc_base/ref_counted_object.h"
- #include "rtc_base/system/rtc_export.h"
- #include "rtc_base/thread.h"
- namespace rtc {
- class Location;
- }
- namespace webrtc {
- template <typename R>
- class ReturnType {
- public:
- template <typename C, typename M, typename... Args>
- void Invoke(C* c, M m, Args&&... args) {
- r_ = (c->*m)(std::forward<Args>(args)...);
- }
- R moved_result() { return std::move(r_); }
- private:
- R r_;
- };
- template <>
- class ReturnType<void> {
- public:
- template <typename C, typename M, typename... Args>
- void Invoke(C* c, M m, Args&&... args) {
- (c->*m)(std::forward<Args>(args)...);
- }
- void moved_result() {}
- };
- template <typename C, typename R, typename... Args>
- class MethodCall : public QueuedTask {
- public:
- typedef R (C::*Method)(Args...);
- MethodCall(C* c, Method m, Args&&... args)
- : c_(c),
- m_(m),
- args_(std::forward_as_tuple(std::forward<Args>(args)...)) {}
- R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
- if (t->IsCurrent()) {
- Invoke(std::index_sequence_for<Args...>());
- } else {
- t->PostTask(std::unique_ptr<QueuedTask>(this));
- event_.Wait(rtc::Event::kForever);
- }
- return r_.moved_result();
- }
- private:
- bool Run() override {
- Invoke(std::index_sequence_for<Args...>());
- event_.Set();
- return false;
- }
- template <size_t... Is>
- void Invoke(std::index_sequence<Is...>) {
- r_.Invoke(c_, m_, std::move(std::get<Is>(args_))...);
- }
- C* c_;
- Method m_;
- ReturnType<R> r_;
- std::tuple<Args&&...> args_;
- rtc::Event event_;
- };
- template <typename C, typename R, typename... Args>
- class ConstMethodCall : public QueuedTask {
- public:
- typedef R (C::*Method)(Args...) const;
- ConstMethodCall(const C* c, Method m, Args&&... args)
- : c_(c),
- m_(m),
- args_(std::forward_as_tuple(std::forward<Args>(args)...)) {}
- R Marshal(const rtc::Location& posted_from, rtc::Thread* t) {
- if (t->IsCurrent()) {
- Invoke(std::index_sequence_for<Args...>());
- } else {
- t->PostTask(std::unique_ptr<QueuedTask>(this));
- event_.Wait(rtc::Event::kForever);
- }
- return r_.moved_result();
- }
- private:
- bool Run() override {
- Invoke(std::index_sequence_for<Args...>());
- event_.Set();
- return false;
- }
- template <size_t... Is>
- void Invoke(std::index_sequence<Is...>) {
- r_.Invoke(c_, m_, std::move(std::get<Is>(args_))...);
- }
- const C* c_;
- Method m_;
- ReturnType<R> r_;
- std::tuple<Args&&...> args_;
- rtc::Event event_;
- };
- #define PROXY_MAP_BOILERPLATE(c) \
- template <class INTERNAL_CLASS> \
- class c##ProxyWithInternal; \
- typedef c##ProxyWithInternal<c##Interface> c##Proxy; \
- template <class INTERNAL_CLASS> \
- class c##ProxyWithInternal : public c##Interface { \
- protected: \
- typedef c##Interface C; \
- \
- public: \
- const INTERNAL_CLASS* internal() const { return c_; } \
- INTERNAL_CLASS* internal() { return c_; }
- #define END_PROXY_MAP() \
- };
- #define SIGNALING_PROXY_MAP_BOILERPLATE(c) \
- protected: \
- c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \
- : signaling_thread_(signaling_thread), c_(c) {} \
- \
- private: \
- mutable rtc::Thread* signaling_thread_;
- #define WORKER_PROXY_MAP_BOILERPLATE(c) \
- protected: \
- c##ProxyWithInternal(rtc::Thread* signaling_thread, \
- rtc::Thread* worker_thread, INTERNAL_CLASS* c) \
- : signaling_thread_(signaling_thread), \
- worker_thread_(worker_thread), \
- c_(c) {} \
- \
- private: \
- mutable rtc::Thread* signaling_thread_; \
- mutable rtc::Thread* worker_thread_;
- #define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
- protected: \
- ~c##ProxyWithInternal() { \
- MethodCall<c##ProxyWithInternal, void> call( \
- this, &c##ProxyWithInternal::DestroyInternal); \
- call.Marshal(RTC_FROM_HERE, destructor_thread()); \
- } \
- \
- private: \
- void DestroyInternal() { c_ = nullptr; } \
- rtc::scoped_refptr<INTERNAL_CLASS> c_;
- #define OWNED_PROXY_MAP_BOILERPLATE(c) \
- public: \
- ~c##ProxyWithInternal() { \
- MethodCall<c##ProxyWithInternal, void> call( \
- this, &c##ProxyWithInternal::DestroyInternal); \
- call.Marshal(RTC_FROM_HERE, destructor_thread()); \
- } \
- \
- private: \
- void DestroyInternal() { delete c_; } \
- INTERNAL_CLASS* c_;
- #define BEGIN_SIGNALING_PROXY_MAP(c) \
- PROXY_MAP_BOILERPLATE(c) \
- SIGNALING_PROXY_MAP_BOILERPLATE(c) \
- REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
- public: \
- static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
- rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \
- return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
- c); \
- }
- #define BEGIN_PROXY_MAP(c) \
- PROXY_MAP_BOILERPLATE(c) \
- WORKER_PROXY_MAP_BOILERPLATE(c) \
- REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \
- public: \
- static rtc::scoped_refptr<c##ProxyWithInternal> Create( \
- rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
- INTERNAL_CLASS* c) { \
- return new rtc::RefCountedObject<c##ProxyWithInternal>(signaling_thread, \
- worker_thread, c); \
- }
- #define BEGIN_OWNED_PROXY_MAP(c) \
- PROXY_MAP_BOILERPLATE(c) \
- WORKER_PROXY_MAP_BOILERPLATE(c) \
- OWNED_PROXY_MAP_BOILERPLATE(c) \
- public: \
- static std::unique_ptr<c##Interface> Create( \
- rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \
- std::unique_ptr<INTERNAL_CLASS> c) { \
- return std::unique_ptr<c##Interface>(new c##ProxyWithInternal( \
- signaling_thread, worker_thread, c.release())); \
- }
- #define PROXY_SIGNALING_THREAD_DESTRUCTOR() \
- private: \
- rtc::Thread* destructor_thread() const { return signaling_thread_; } \
- \
- public:
- #define PROXY_WORKER_THREAD_DESTRUCTOR() \
- private: \
- rtc::Thread* destructor_thread() const { return worker_thread_; } \
- \
- public:
- #define PROXY_METHOD0(r, method) \
- r method() override { \
- MethodCall<C, r> call(c_, &C::method); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_CONSTMETHOD0(r, method) \
- r method() const override { \
- ConstMethodCall<C, r> call(c_, &C::method); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_METHOD1(r, method, t1) \
- r method(t1 a1) override { \
- MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_CONSTMETHOD1(r, method, t1) \
- r method(t1 a1) const override { \
- ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_METHOD2(r, method, t1, t2) \
- r method(t1 a1, t2 a2) override { \
- MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
- std::move(a2)); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_METHOD3(r, method, t1, t2, t3) \
- r method(t1 a1, t2 a2, t3 a3) override { \
- MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
- std::move(a2), std::move(a3)); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_METHOD4(r, method, t1, t2, t3, t4) \
- r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \
- MethodCall<C, r, t1, t2, t3, t4> call(c_, &C::method, std::move(a1), \
- std::move(a2), std::move(a3), \
- std::move(a4)); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \
- r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \
- MethodCall<C, r, t1, t2, t3, t4, t5> call(c_, &C::method, std::move(a1), \
- std::move(a2), std::move(a3), \
- std::move(a4), std::move(a5)); \
- return call.Marshal(RTC_FROM_HERE, signaling_thread_); \
- }
- #define PROXY_WORKER_METHOD0(r, method) \
- r method() override { \
- MethodCall<C, r> call(c_, &C::method); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_CONSTMETHOD0(r, method) \
- r method() const override { \
- ConstMethodCall<C, r> call(c_, &C::method); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_METHOD1(r, method, t1) \
- r method(t1 a1) override { \
- MethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \
- r method(t1 a1) const override { \
- ConstMethodCall<C, r, t1> call(c_, &C::method, std::move(a1)); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_METHOD2(r, method, t1, t2) \
- r method(t1 a1, t2 a2) override { \
- MethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
- std::move(a2)); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \
- r method(t1 a1, t2 a2) const override { \
- ConstMethodCall<C, r, t1, t2> call(c_, &C::method, std::move(a1), \
- std::move(a2)); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \
- r method(t1 a1, t2 a2, t3 a3) override { \
- MethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
- std::move(a2), std::move(a3)); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \
- r method(t1 a1, t2 a2, t3 a3) const override { \
- ConstMethodCall<C, r, t1, t2, t3> call(c_, &C::method, std::move(a1), \
- std::move(a2), std::move(a3)); \
- return call.Marshal(RTC_FROM_HERE, worker_thread_); \
- }
- #define BYPASS_PROXY_CONSTMETHOD0(r, method) \
- r method() const override { \
- static_assert( \
- std::is_same<r, rtc::Thread*>::value || !std::is_pointer<r>::value, \
- "Type is a pointer"); \
- static_assert(!std::is_reference<r>::value, "Type is a reference"); \
- return c_->method(); \
- }
- }
- #endif
|