diff --git a/api/BUILD.gn b/api/BUILD.gn index d82c28d7b4..45f555c815 100644 --- a/api/BUILD.gn +++ b/api/BUILD.gn @@ -145,6 +145,7 @@ rtc_library("libjingle_peerconnection_api") { "peer_connection_interface.cc", "peer_connection_interface.h", "peer_connection_proxy.h", + "proxy.cc", "proxy.h", "rtp_receiver_interface.cc", "rtp_receiver_interface.h", diff --git a/api/proxy.cc b/api/proxy.cc new file mode 100644 index 0000000000..e668285ba2 --- /dev/null +++ b/api/proxy.cc @@ -0,0 +1,37 @@ +/* + * Copyright 2017 The WebRTC project authors. All Rights Reserved. + * + * Use of this source code is governed by a BSD-style license + * that can be found in the LICENSE file in the root of the source + * tree. An additional intellectual property rights grant can be found + * in the file PATENTS. All contributing project authors may + * be found in the AUTHORS file in the root of the source tree. + */ + +#include "api/proxy.h" + +namespace webrtc { +namespace internal { + +SynchronousMethodCall::SynchronousMethodCall(rtc::MessageHandler* proxy) + : proxy_(proxy) {} + +SynchronousMethodCall::~SynchronousMethodCall() = default; + +void SynchronousMethodCall::Invoke(const rtc::Location& posted_from, + rtc::Thread* t) { + if (t->IsCurrent()) { + proxy_->OnMessage(nullptr); + } else { + t->Post(posted_from, this, 0); + e_.Wait(rtc::Event::kForever); + } +} + +void SynchronousMethodCall::OnMessage(rtc::Message*) { + proxy_->OnMessage(nullptr); + e_.Set(); +} + +} // namespace internal +} // namespace webrtc diff --git a/api/proxy.h b/api/proxy.h index 474b9a6d3b..385992e659 100644 --- a/api/proxy.h +++ b/api/proxy.h @@ -70,6 +70,106 @@ class Location; namespace webrtc { +template +class ReturnType { + public: + template + void Invoke(C* c, M m, Args&&... args) { + r_ = (c->*m)(std::forward(args)...); + } + + R moved_result() { return std::move(r_); } + + private: + R r_; +}; + +template <> +class ReturnType { + public: + template + void Invoke(C* c, M m, Args&&... args) { + (c->*m)(std::forward(args)...); + } + + void moved_result() {} +}; + +namespace internal { + +class RTC_EXPORT SynchronousMethodCall : public rtc::MessageData, + public rtc::MessageHandler { + public: + explicit SynchronousMethodCall(rtc::MessageHandler* proxy); + ~SynchronousMethodCall() override; + + void Invoke(const rtc::Location& posted_from, rtc::Thread* t); + + private: + void OnMessage(rtc::Message*) override; + + rtc::Event e_; + rtc::MessageHandler* proxy_; +}; + +} // namespace internal + +template +class MethodCall : public rtc::Message, public rtc::MessageHandler { + 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)...)) {} + + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); + } + + private: + void OnMessage(rtc::Message*) { Invoke(std::index_sequence_for()); } + + template + void Invoke(std::index_sequence) { + r_.Invoke(c_, m_, std::move(std::get(args_))...); + } + + C* c_; + Method m_; + ReturnType r_; + std::tuple args_; +}; + +template +class ConstMethodCall : public rtc::Message, public rtc::MessageHandler { + 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)...)) {} + + R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { + internal::SynchronousMethodCall(this).Invoke(posted_from, t); + return r_.moved_result(); + } + + private: + void OnMessage(rtc::Message*) { Invoke(std::index_sequence_for()); } + + template + void Invoke(std::index_sequence) { + r_.Invoke(c_, m_, std::move(std::get(args_))...); + } + + const C* c_; + Method m_; + ReturnType r_; + std::tuple args_; +}; + // Helper macros to reduce code duplication. #define PROXY_MAP_BOILERPLATE(c) \ template \ @@ -113,14 +213,16 @@ namespace webrtc { // Note that the destructor is protected so that the proxy can only be // destroyed via RefCountInterface. -#define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ - protected: \ - ~c##ProxyWithInternal() { \ - destructor_thread()->template Invoke(RTC_FROM_HERE, \ - [&] { c_ = nullptr; }); \ - } \ - \ - private: \ +#define REFCOUNTED_PROXY_MAP_BOILERPLATE(c) \ + protected: \ + ~c##ProxyWithInternal() { \ + MethodCall call( \ + this, &c##ProxyWithInternal::DestroyInternal); \ + call.Marshal(RTC_FROM_HERE, destructor_thread()); \ + } \ + \ + private: \ + void DestroyInternal() { c_ = nullptr; } \ rtc::scoped_refptr c_; // Note: This doesn't use a unique_ptr, because it intends to handle a corner @@ -128,14 +230,16 @@ namespace webrtc { // this proxy object. If relying on a unique_ptr to delete the object, its // inner pointer would be set to null before this reentrant callback would have // a chance to run, resulting in a segfault. -#define OWNED_PROXY_MAP_BOILERPLATE(c) \ - public: \ - ~c##ProxyWithInternal() { \ - destructor_thread()->template Invoke(RTC_FROM_HERE, \ - [&] { delete c_; }); \ - } \ - \ - private: \ +#define OWNED_PROXY_MAP_BOILERPLATE(c) \ + public: \ + ~c##ProxyWithInternal() { \ + MethodCall 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) \ @@ -185,95 +289,112 @@ namespace webrtc { \ public: // NOLINTNEXTLINE -#define PROXY_METHOD0_BASE(t, modifier, r, method) \ - r method() modifier override { \ - return t->template Invoke(RTC_FROM_HERE, [&] { return c_->method(); }); \ +#define PROXY_METHOD0(r, method) \ + r method() override { \ + MethodCall call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD1_BASE(t, modifier, r, method, t1) \ - r method(t1 a1) modifier override { \ - return t->template Invoke(RTC_FROM_HERE, \ - [&] { return c_->method(std::move(a1)); }); \ +#define PROXY_CONSTMETHOD0(r, method) \ + r method() const override { \ + ConstMethodCall call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD2_BASE(t, modifier, r, method, t1, t2) \ - r method(t1 a1, t2 a2) modifier override { \ - return t->template Invoke(RTC_FROM_HERE, [&] { \ - return c_->method(std::move(a1), std::move(a2)); \ - }); \ +#define PROXY_METHOD1(r, method, t1) \ + r method(t1 a1) override { \ + MethodCall call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD3_BASE(t, modifier, r, method, t1, t2, t3) \ - r method(t1 a1, t2 a2, t3 a3) modifier override { \ - return t->template Invoke(RTC_FROM_HERE, [&] { \ - return c_->method(std::move(a1), std::move(a2), std::move(a3)); \ - }); \ +#define PROXY_CONSTMETHOD1(r, method, t1) \ + r method(t1 a1) const override { \ + ConstMethodCall call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD4_BASE(t, modifier, r, method, t1, t2, t3, t4) \ - r method(t1 a1, t2 a2, t3 a3, t4 a4) modifier override { \ - return t->template Invoke(RTC_FROM_HERE, [&] { \ - return c_->method(std::move(a1), std::move(a2), std::move(a3), \ - std::move(a4)); \ - }); \ +#define PROXY_METHOD2(r, method, t1, t2) \ + r method(t1 a1, t2 a2) override { \ + MethodCall call(c_, &C::method, std::move(a1), \ + std::move(a2)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD5_BASE(t, modifier, r, method, t1, t2, t3, t4, t5) \ - r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) modifier override { \ - return t->template Invoke(RTC_FROM_HERE, [&] { \ - return c_->method(std::move(a1), std::move(a2), std::move(a3), \ - std::move(a4), std::move(a5)); \ - }); \ +#define PROXY_METHOD3(r, method, t1, t2, t3) \ + r method(t1 a1, t2 a2, t3 a3) override { \ + MethodCall call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3)); \ + return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD0(r, method) \ - PROXY_METHOD0_BASE(signaling_thread_, , r, method) +#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \ + r method(t1 a1, t2 a2, t3 a3, t4 a4) override { \ + MethodCall 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_CONSTMETHOD0(r, method) \ - PROXY_METHOD0_BASE(signaling_thread_, const, r, method) - -#define PROXY_METHOD1(r, method, t1) \ - PROXY_METHOD1_BASE(signaling_thread_, , r, method, t1) - -#define PROXY_CONSTMETHOD1(r, method, t1) \ - PROXY_METHOD1_BASE(signaling_thread_, const, r, method, t1) - -#define PROXY_METHOD2(r, method, t1, t2) \ - PROXY_METHOD2_BASE(signaling_thread_, , r, method, t1, t2) - -#define PROXY_METHOD3(r, method, t1, t2, t3) \ - PROXY_METHOD3_BASE(signaling_thread_, , r, method, t1, t2, t3) - -#define PROXY_METHOD4(r, method, t1, t2, t3, t4) \ - PROXY_METHOD4_BASE(signaling_thread_, , r, method, t1, t2, t3, t4) - -#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \ - PROXY_METHOD5_BASE(signaling_thread_, , r, method, t1, t2, t3, t4, t5) +#define PROXY_METHOD5(r, method, t1, t2, t3, t4, t5) \ + r method(t1 a1, t2 a2, t3 a3, t4 a4, t5 a5) override { \ + MethodCall 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 methods which should be invoked on the worker thread. -#define PROXY_WORKER_METHOD0(r, method) \ - PROXY_METHOD0_BASE(worker_thread_, , r, method) +#define PROXY_WORKER_METHOD0(r, method) \ + r method() override { \ + MethodCall call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } -#define PROXY_WORKER_CONSTMETHOD0(r, method) \ - PROXY_METHOD0_BASE(worker_thread_, const, r, method) +#define PROXY_WORKER_CONSTMETHOD0(r, method) \ + r method() const override { \ + ConstMethodCall call(c_, &C::method); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } -#define PROXY_WORKER_METHOD1(r, method, t1) \ - PROXY_METHOD1_BASE(worker_thread_, , r, method, t1) +#define PROXY_WORKER_METHOD1(r, method, t1) \ + r method(t1 a1) override { \ + MethodCall call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } -#define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \ - PROXY_METHOD1_BASE(worker_thread_, const, r, method, t1) +#define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \ + r method(t1 a1) const override { \ + ConstMethodCall call(c_, &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } -#define PROXY_WORKER_METHOD2(r, method, t1, t2) \ - PROXY_METHOD2_BASE(worker_thread_, , r, method, t1, t2) +#define PROXY_WORKER_METHOD2(r, method, t1, t2) \ + r method(t1 a1, t2 a2) override { \ + MethodCall 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) \ - PROXY_METHOD2_BASE(worker_thread_, const, r, method, t1, t2) +#define PROXY_WORKER_CONSTMETHOD2(r, method, t1, t2) \ + r method(t1 a1, t2 a2) const override { \ + ConstMethodCall 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) \ - PROXY_METHOD3_BASE(worker_thread_, , r, method, t1, t2, t3) +#define PROXY_WORKER_METHOD3(r, method, t1, t2, t3) \ + r method(t1 a1, t2 a2, t3 a3) override { \ + MethodCall 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) \ - PROXY_METHOD3_BASE(worker_thread_, const, r, method, t1, t2, t3) +#define PROXY_WORKER_CONSTMETHOD3(r, method, t1, t2) \ + r method(t1 a1, t2 a2, t3 a3) const override { \ + ConstMethodCall call(c_, &C::method, std::move(a1), \ + std::move(a2), std::move(a3)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } } // namespace webrtc diff --git a/pc/peer_connection_factory.cc b/pc/peer_connection_factory.cc index 606d32ca17..4523121b58 100644 --- a/pc/peer_connection_factory.cc +++ b/pc/peer_connection_factory.cc @@ -55,8 +55,9 @@ CreateModularPeerConnectionFactory( std::move(dependencies))); // Call Initialize synchronously but make sure it is executed on // |signaling_thread|. - bool result = pc_factory->signaling_thread()->Invoke( - RTC_FROM_HERE, [&] { return pc_factory->Initialize(); }); + MethodCall call( + pc_factory.get(), &PeerConnectionFactory::Initialize); + bool result = call.Marshal(RTC_FROM_HERE, pc_factory->signaling_thread()); if (!result) { return nullptr;