From d99a200fad07a23e4e31daab50b7b55bf364ad06 Mon Sep 17 00:00:00 2001 From: deadbeef Date: Wed, 18 Jan 2017 08:55:23 -0800 Subject: [PATCH] Adding some features to proxy.h, and restructuring the macros. New features are: - Invoke a destructor on the worker thread. - Make proxy wrapper for a non-refcounted object. - Ability to use unique_ptrs (as arguments or return values). These features are needed by this CL: https://codereview.webrtc.org/2632613002/ BUG=None Review-Url: https://codereview.webrtc.org/2628343003 Cr-Commit-Position: refs/heads/master@{#16151} --- webrtc/api/datachannel.h | 3 +- webrtc/api/dtmfsender.h | 3 +- webrtc/api/mediastreamproxy.h | 9 +- webrtc/api/mediastreamtrackproxy.h | 9 +- webrtc/api/peerconnectionfactoryproxy.h | 65 +--- webrtc/api/peerconnectionproxy.h | 36 ++- webrtc/api/proxy.h | 380 +++++++++++++++--------- webrtc/api/proxy_unittest.cc | 85 +++++- webrtc/api/rtpreceiverinterface.h | 15 +- webrtc/api/rtpsenderinterface.h | 19 +- webrtc/api/videosourceproxy.h | 3 +- 11 files changed, 398 insertions(+), 229 deletions(-) diff --git a/webrtc/api/datachannel.h b/webrtc/api/datachannel.h index 19f95df444..cdb2e627b6 100644 --- a/webrtc/api/datachannel.h +++ b/webrtc/api/datachannel.h @@ -272,6 +272,7 @@ class DataChannel : public DataChannelInterface, // Define proxy for DataChannelInterface. BEGIN_SIGNALING_PROXY_MAP(DataChannel) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_METHOD1(void, RegisterObserver, DataChannelObserver*) PROXY_METHOD0(void, UnregisterObserver) PROXY_CONSTMETHOD0(std::string, label) @@ -290,7 +291,7 @@ BEGIN_SIGNALING_PROXY_MAP(DataChannel) PROXY_CONSTMETHOD0(uint64_t, buffered_amount) PROXY_METHOD0(void, Close) PROXY_METHOD1(bool, Send, const DataBuffer&) -END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/dtmfsender.h b/webrtc/api/dtmfsender.h index c85557f2e1..d4e8f06d9e 100644 --- a/webrtc/api/dtmfsender.h +++ b/webrtc/api/dtmfsender.h @@ -105,6 +105,7 @@ class DtmfSender // Define proxy for DtmfSenderInterface. BEGIN_SIGNALING_PROXY_MAP(DtmfSender) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_METHOD1(void, RegisterObserver, DtmfSenderObserverInterface*) PROXY_METHOD0(void, UnregisterObserver) PROXY_METHOD0(bool, CanInsertDtmf) @@ -113,7 +114,7 @@ BEGIN_SIGNALING_PROXY_MAP(DtmfSender) PROXY_CONSTMETHOD0(std::string, tones) PROXY_CONSTMETHOD0(int, duration) PROXY_CONSTMETHOD0(int, inter_tone_gap) -END_SIGNALING_PROXY() +END_PROXY_MAP() // Get DTMF code from the DTMF event character. bool GetDtmfCode(char tone, int* code); diff --git a/webrtc/api/mediastreamproxy.h b/webrtc/api/mediastreamproxy.h index 06f8eb3b2c..4253a093c4 100644 --- a/webrtc/api/mediastreamproxy.h +++ b/webrtc/api/mediastreamproxy.h @@ -17,20 +17,23 @@ namespace webrtc { BEGIN_SIGNALING_PROXY_MAP(MediaStream) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(std::string, label) PROXY_METHOD0(AudioTrackVector, GetAudioTracks) PROXY_METHOD0(VideoTrackVector, GetVideoTracks) PROXY_METHOD1(rtc::scoped_refptr, - FindAudioTrack, const std::string&) + FindAudioTrack, + const std::string&) PROXY_METHOD1(rtc::scoped_refptr, - FindVideoTrack, const std::string&) + FindVideoTrack, + const std::string&) PROXY_METHOD1(bool, AddTrack, AudioTrackInterface*) PROXY_METHOD1(bool, AddTrack, VideoTrackInterface*) PROXY_METHOD1(bool, RemoveTrack, AudioTrackInterface*) PROXY_METHOD1(bool, RemoveTrack, VideoTrackInterface*) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/mediastreamtrackproxy.h b/webrtc/api/mediastreamtrackproxy.h index fc73536aff..da371f8cf6 100644 --- a/webrtc/api/mediastreamtrackproxy.h +++ b/webrtc/api/mediastreamtrackproxy.h @@ -20,6 +20,7 @@ namespace webrtc { BEGIN_SIGNALING_PROXY_MAP(AudioTrack) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(std::string, kind) PROXY_CONSTMETHOD0(std::string, id) PROXY_CONSTMETHOD0(TrackState, state) @@ -28,14 +29,14 @@ BEGIN_SIGNALING_PROXY_MAP(AudioTrack) PROXY_METHOD1(void, AddSink, AudioTrackSinkInterface*) PROXY_METHOD1(void, RemoveSink, AudioTrackSinkInterface*) PROXY_METHOD1(bool, GetSignalLevel, int*) - PROXY_METHOD0(rtc::scoped_refptr, - GetAudioProcessor) + PROXY_METHOD0(rtc::scoped_refptr, GetAudioProcessor) PROXY_METHOD1(bool, set_enabled, bool) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_SIGNALING_PROXY() +END_PROXY_MAP() BEGIN_PROXY_MAP(VideoTrack) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(std::string, kind) PROXY_CONSTMETHOD0(std::string, id) PROXY_CONSTMETHOD0(TrackState, state) @@ -52,7 +53,7 @@ BEGIN_PROXY_MAP(VideoTrack) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/peerconnectionfactoryproxy.h b/webrtc/api/peerconnectionfactoryproxy.h index 227a685b7e..d41aad25fe 100644 --- a/webrtc/api/peerconnectionfactoryproxy.h +++ b/webrtc/api/peerconnectionfactoryproxy.h @@ -22,32 +22,21 @@ namespace webrtc { BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_METHOD1(void, SetOptions, const Options&) - // Can't use PROXY_METHOD5 because unique_ptr must be moved. - // TODO(tommi,hbos): Use of templates to support unique_ptr? - rtc::scoped_refptr CreatePeerConnection( - const PeerConnectionInterface::RTCConfiguration& a1, - const MediaConstraintsInterface* a2, - std::unique_ptr a3, - std::unique_ptr a4, - PeerConnectionObserver* a5) override { - return signaling_thread_ - ->Invoke>( - RTC_FROM_HERE, - rtc::Bind(&PeerConnectionFactoryProxy::CreatePeerConnection_ot, - this, a1, a2, a3.release(), a4.release(), a5)); - } - rtc::scoped_refptr CreatePeerConnection( - const PeerConnectionInterface::RTCConfiguration& a1, - std::unique_ptr a3, - std::unique_ptr a4, - PeerConnectionObserver* a5) override { - return signaling_thread_ - ->Invoke>( - RTC_FROM_HERE, - rtc::Bind(&PeerConnectionFactoryProxy::CreatePeerConnection_ot, - this, a1, a3.release(), a4.release(), a5)); - } + PROXY_METHOD5(rtc::scoped_refptr, + CreatePeerConnection, + const PeerConnectionInterface::RTCConfiguration&, + const MediaConstraintsInterface*, + std::unique_ptr, + std::unique_ptr, + PeerConnectionObserver*); + PROXY_METHOD4(rtc::scoped_refptr, + CreatePeerConnection, + const PeerConnectionInterface::RTCConfiguration&, + std::unique_ptr, + std::unique_ptr, + PeerConnectionObserver*); PROXY_METHOD1(rtc::scoped_refptr, CreateLocalMediaStream, const std::string&) PROXY_METHOD1(rtc::scoped_refptr, @@ -75,31 +64,7 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnectionFactory) PROXY_METHOD1(bool, StartRtcEventLog, rtc::PlatformFile) PROXY_METHOD2(bool, StartRtcEventLog, rtc::PlatformFile, int64_t) PROXY_METHOD0(void, StopRtcEventLog) - - private: - rtc::scoped_refptr CreatePeerConnection_ot( - const PeerConnectionInterface::RTCConfiguration& a1, - const MediaConstraintsInterface* a2, - cricket::PortAllocator* a3, - rtc::RTCCertificateGeneratorInterface* a4, - PeerConnectionObserver* a5) { - std::unique_ptr ptr_a3(a3); - std::unique_ptr ptr_a4(a4); - return c_->CreatePeerConnection(a1, a2, std::move(ptr_a3), - std::move(ptr_a4), a5); - } - - rtc::scoped_refptr CreatePeerConnection_ot( - const PeerConnectionInterface::RTCConfiguration& a1, - cricket::PortAllocator* a3, - rtc::RTCCertificateGeneratorInterface* a4, - PeerConnectionObserver* a5) { - std::unique_ptr ptr_a3(a3); - std::unique_ptr ptr_a4(a4); - return c_->CreatePeerConnection(a1, std::move(ptr_a3), std::move(ptr_a4), - a5); - } - END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/peerconnectionproxy.h b/webrtc/api/peerconnectionproxy.h index 1609a751e1..ed707b3c45 100644 --- a/webrtc/api/peerconnectionproxy.h +++ b/webrtc/api/peerconnectionproxy.h @@ -18,10 +18,9 @@ namespace webrtc { // Define proxy for PeerConnectionInterface. BEGIN_SIGNALING_PROXY_MAP(PeerConnection) - PROXY_METHOD0(rtc::scoped_refptr, - local_streams) - PROXY_METHOD0(rtc::scoped_refptr, - remote_streams) + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_METHOD0(rtc::scoped_refptr, local_streams) + PROXY_METHOD0(rtc::scoped_refptr, remote_streams) PROXY_METHOD1(bool, AddStream, MediaStreamInterface*) PROXY_METHOD1(void, RemoveStream, MediaStreamInterface*) PROXY_METHOD2(rtc::scoped_refptr, @@ -30,7 +29,8 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) std::vector) PROXY_METHOD1(bool, RemoveTrack, RtpSenderInterface*) PROXY_METHOD1(rtc::scoped_refptr, - CreateDtmfSender, AudioTrackInterface*) + CreateDtmfSender, + AudioTrackInterface*) PROXY_METHOD2(rtc::scoped_refptr, CreateSender, const std::string&, @@ -39,12 +39,16 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) GetSenders) PROXY_CONSTMETHOD0(std::vector>, GetReceivers) - PROXY_METHOD3(bool, GetStats, StatsObserver*, + PROXY_METHOD3(bool, + GetStats, + StatsObserver*, MediaStreamTrackInterface*, StatsOutputLevel) PROXY_METHOD1(void, GetStats, RTCStatsCollectorCallback*) PROXY_METHOD2(rtc::scoped_refptr, - CreateDataChannel, const std::string&, const DataChannelInit*) + CreateDataChannel, + const std::string&, + const DataChannelInit*) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, local_description) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, remote_description) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, @@ -55,9 +59,13 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) current_local_description) PROXY_CONSTMETHOD0(const SessionDescriptionInterface*, current_remote_description) - PROXY_METHOD2(void, CreateOffer, CreateSessionDescriptionObserver*, + PROXY_METHOD2(void, + CreateOffer, + CreateSessionDescriptionObserver*, const MediaConstraintsInterface*) - PROXY_METHOD2(void, CreateAnswer, CreateSessionDescriptionObserver*, + PROXY_METHOD2(void, + CreateAnswer, + CreateSessionDescriptionObserver*, const MediaConstraintsInterface*) PROXY_METHOD2(void, CreateOffer, @@ -67,9 +75,13 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) CreateAnswer, CreateSessionDescriptionObserver*, const RTCOfferAnswerOptions&) - PROXY_METHOD2(void, SetLocalDescription, SetSessionDescriptionObserver*, + PROXY_METHOD2(void, + SetLocalDescription, + SetSessionDescriptionObserver*, SessionDescriptionInterface*) - PROXY_METHOD2(void, SetRemoteDescription, SetSessionDescriptionObserver*, + PROXY_METHOD2(void, + SetRemoteDescription, + SetSessionDescriptionObserver*, SessionDescriptionInterface*) PROXY_METHOD0(PeerConnectionInterface::RTCConfiguration, GetConfiguration); PROXY_METHOD2(bool, @@ -90,7 +102,7 @@ BEGIN_SIGNALING_PROXY_MAP(PeerConnection) PROXY_METHOD2(bool, StartRtcEventLog, rtc::PlatformFile, int64_t) PROXY_METHOD0(void, StopRtcEventLog) PROXY_METHOD0(void, Close) -END_SIGNALING_PROXY() +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/proxy.h b/webrtc/api/proxy.h index 746a758ba4..51cdd296cf 100644 --- a/webrtc/api/proxy.h +++ b/webrtc/api/proxy.h @@ -28,13 +28,14 @@ // }; // // BEGIN_PROXY_MAP(Test) +// PROXY_SIGNALING_THREAD_DESTRUCTOR() // PROXY_METHOD0(std::string, FooA) // PROXY_CONSTMETHOD1(std::string, FooB, arg1) // PROXY_WORKER_METHOD1(std::string, FooC, arg1) -// END_PROXY() +// END_PROXY_MAP() // -// where the first two methods are invoked on the signaling thread, -// and the third is invoked on the worker thread. +// Where the destructor and first two methods are invoked on the signaling +// thread, and the third is invoked on the worker thread. // // The proxy can be created using // @@ -43,6 +44,9 @@ // // The variant defined with BEGIN_SIGNALING_PROXY_MAP is unaware of // the worker thread, and invokes all methods on the signaling thread. +// +// The variant defined with BEGIN_OWNED_PROXY_MAP does not use +// refcounting, and instead just takes ownership of the object being proxied. #ifndef WEBRTC_API_PROXY_H_ #define WEBRTC_API_PROXY_H_ @@ -59,24 +63,31 @@ class ReturnType { public: template void Invoke(C* c, M m) { r_ = (c->*m)(); } - template - void Invoke(C* c, M m, T1 a1) { r_ = (c->*m)(a1); } - template - void Invoke(C* c, M m, T1 a1, T2 a2) { r_ = (c->*m)(a1, a2); } - template - void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { r_ = (c->*m)(a1, a2, a3); } + template + void Invoke(C* c, M m, T1 a1) { + r_ = (c->*m)(std::move(a1)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2) { + r_ = (c->*m)(std::move(a1), std::move(a2)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { + r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3)); + } template void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4) { - r_ = (c->*m)(a1, a2, a3, a4); + r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4)); } template void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) { - r_ = (c->*m)(a1, a2, a3, a4, a5); + r_ = (c->*m)(std::move(a1), std::move(a2), std::move(a3), std::move(a4), + std::move(a5)); } - R value() { return r_; } + R moved_result() { return std::move(r_); } private: R r_; @@ -87,14 +98,20 @@ class ReturnType { public: template void Invoke(C* c, M m) { (c->*m)(); } - template - void Invoke(C* c, M m, T1 a1) { (c->*m)(a1); } - template - void Invoke(C* c, M m, T1 a1, T2 a2) { (c->*m)(a1, a2); } - template - void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { (c->*m)(a1, a2, a3); } + template + void Invoke(C* c, M m, T1 a1) { + (c->*m)(std::move(a1)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2) { + (c->*m)(std::move(a1), std::move(a2)); + } + template + void Invoke(C* c, M m, T1 a1, T2 a2, T3 a3) { + (c->*m)(std::move(a1), std::move(a2), std::move(a3)); + } - void value() {} + void moved_result() {} }; namespace internal { @@ -134,7 +151,7 @@ class MethodCall0 : public rtc::Message, R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: @@ -154,7 +171,7 @@ class ConstMethodCall0 : public rtc::Message, R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: @@ -170,15 +187,15 @@ class MethodCall1 : public rtc::Message, public rtc::MessageHandler { public: typedef R (C::*Method)(T1 a1); - MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} + MethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(std::move(a1)) {} R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); } + void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, std::move(a1_)); } C* c_; Method m_; @@ -191,15 +208,15 @@ class ConstMethodCall1 : public rtc::Message, public rtc::MessageHandler { public: typedef R (C::*Method)(T1 a1) const; - ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(a1) {} + ConstMethodCall1(C* c, Method m, T1 a1) : c_(c), m_(m), a1_(std::move(a1)) {} R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_); } + void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, std::move(a1_)); } C* c_; Method m_; @@ -212,15 +229,18 @@ class MethodCall2 : public rtc::Message, public rtc::MessageHandler { public: typedef R (C::*Method)(T1 a1, T2 a2); - MethodCall2(C* c, Method m, T1 a1, T2 a2) : c_(c), m_(m), a1_(a1), a2_(a2) {} + MethodCall2(C* c, Method m, T1 a1, T2 a2) + : c_(c), m_(m), a1_(std::move(a1)), a2_(std::move(a2)) {} R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_)); + } C* c_; Method m_; @@ -235,15 +255,21 @@ class MethodCall3 : public rtc::Message, public: typedef R (C::*Method)(T1 a1, T2 a2, T3 a3); MethodCall3(C* c, Method m, T1 a1, T2 a2, T3 a3) - : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3) {} + : c_(c), + m_(m), + a1_(std::move(a1)), + a2_(std::move(a2)), + a3_(std::move(a3)) {} R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_)); + } C* c_; Method m_; @@ -260,15 +286,23 @@ class MethodCall4 : public rtc::Message, public: typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4); MethodCall4(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4) - : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4) {} + : c_(c), + m_(m), + a1_(std::move(a1)), + a2_(std::move(a2)), + a3_(std::move(a3)), + a4_(std::move(a4)) {} R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_), + std::move(a4_)); + } C* c_; Method m_; @@ -286,15 +320,24 @@ class MethodCall5 : public rtc::Message, public: typedef R (C::*Method)(T1 a1, T2 a2, T3 a3, T4 a4, T5 a5); MethodCall5(C* c, Method m, T1 a1, T2 a2, T3 a3, T4 a4, T5 a5) - : c_(c), m_(m), a1_(a1), a2_(a2), a3_(a3), a4_(a4), a5_(a5) {} + : c_(c), + m_(m), + a1_(std::move(a1)), + a2_(std::move(a2)), + a3_(std::move(a3)), + a4_(std::move(a4)), + a5_(std::move(a5)) {} R Marshal(const rtc::Location& posted_from, rtc::Thread* t) { internal::SynchronousMethodCall(this).Invoke(posted_from, t); - return r_.value(); + return r_.moved_result(); } private: - void OnMessage(rtc::Message*) { r_.Invoke(c_, m_, a1_, a2_, a3_, a4_, a5_); } + void OnMessage(rtc::Message*) { + r_.Invoke(c_, m_, std::move(a1_), std::move(a2_), std::move(a3_), + std::move(a4_), std::move(a5_)); + } C* c_; Method m_; @@ -306,33 +349,8 @@ class MethodCall5 : public rtc::Message, T5 a5_; }; -#define BEGIN_SIGNALING_PROXY_MAP(c) \ - template \ - class c##ProxyWithInternal; \ - typedef c##ProxyWithInternal c##Proxy; \ - template \ - class c##ProxyWithInternal : public c##Interface { \ - protected: \ - typedef c##Interface C; \ - c##ProxyWithInternal(rtc::Thread* signaling_thread, INTERNAL_CLASS* c) \ - : signaling_thread_(signaling_thread), c_(c) {} \ - ~c##ProxyWithInternal() { \ - MethodCall0 call( \ - this, &c##ProxyWithInternal::Release_s); \ - call.Marshal(RTC_FROM_HERE, signaling_thread_); \ - } \ - \ - public: \ - static rtc::scoped_refptr Create( \ - rtc::Thread* signaling_thread, \ - INTERNAL_CLASS* c) { \ - return new rtc::RefCountedObject(signaling_thread, \ - c); \ - } \ - const INTERNAL_CLASS* internal() const { return c_.get(); } \ - INTERNAL_CLASS* internal() { return c_.get(); } - -#define BEGIN_PROXY_MAP(c) \ +// Helper macros to reduce code duplication. +#define PROXY_MAP_BOILERPLATE(c) \ template \ class c##ProxyWithInternal; \ typedef c##ProxyWithInternal c##Proxy; \ @@ -340,29 +358,104 @@ class MethodCall5 : public rtc::Message, class c##ProxyWithInternal : public c##Interface { \ protected: \ typedef c##Interface C; \ - c##ProxyWithInternal(rtc::Thread* signaling_thread, \ - rtc::Thread* worker_thread, \ - INTERNAL_CLASS* c) \ - : signaling_thread_(signaling_thread), \ - worker_thread_(worker_thread), \ - c_(c) {} \ - ~c##ProxyWithInternal() { \ - MethodCall0 call( \ - this, &c##ProxyWithInternal::Release_s); \ - call.Marshal(RTC_FROM_HERE, signaling_thread_); \ - } \ \ public: \ - static rtc::scoped_refptr Create( \ - rtc::Thread* signaling_thread, \ - rtc::Thread* worker_thread, \ - INTERNAL_CLASS* c) { \ - return new rtc::RefCountedObject( \ - signaling_thread, worker_thread, c); \ - } \ const INTERNAL_CLASS* internal() const { return c_.get(); } \ INTERNAL_CLASS* internal() { return c_.get(); } +#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_; + +// 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() { \ + MethodCall0 call( \ + this, &c##ProxyWithInternal::DestroyInternal); \ + call.Marshal(RTC_FROM_HERE, destructor_thread()); \ + } \ + \ + private: \ + void DestroyInternal() { c_ = nullptr; } \ + rtc::scoped_refptr c_; + +#define OWNED_PROXY_MAP_BOILERPLATE(c) \ + public: \ + ~c##ProxyWithInternal() { \ + MethodCall0 call( \ + this, &c##ProxyWithInternal::DestroyInternal); \ + call.Marshal(RTC_FROM_HERE, destructor_thread()); \ + } \ + \ + private: \ + void DestroyInternal() { c_.reset(nullptr); } \ + std::unique_ptr 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 Create( \ + rtc::Thread* signaling_thread, INTERNAL_CLASS* c) { \ + return new rtc::RefCountedObject(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 Create( \ + rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \ + INTERNAL_CLASS* c) { \ + return new rtc::RefCountedObject(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 Create( \ + rtc::Thread* signaling_thread, rtc::Thread* worker_thread, \ + INTERNAL_CLASS* c) { \ + return std::unique_ptr( \ + new c##ProxyWithInternal(signaling_thread, worker_thread, c)); \ + } + +#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 { \ MethodCall0 call(c_.get(), &C::method); \ @@ -375,72 +468,89 @@ class MethodCall5 : public rtc::Message, return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ } -#define PROXY_METHOD1(r, method, t1) \ - r method(t1 a1) override { \ - MethodCall1 call(c_.get(), &C::method, a1); \ - return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ +#define PROXY_METHOD1(r, method, t1) \ + r method(t1 a1) override { \ + MethodCall1 call(c_.get(), &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 { \ - ConstMethodCall1 call(c_.get(), &C::method, a1); \ - return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ - } - -#define PROXY_METHOD2(r, method, t1, t2) \ - r method(t1 a1, t2 a2) override { \ - MethodCall2 call(c_.get(), &C::method, a1, 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 { \ - MethodCall3 call(c_.get(), &C::method, a1, a2, a3); \ +#define PROXY_CONSTMETHOD1(r, method, t1) \ + r method(t1 a1) const override { \ + ConstMethodCall1 call(c_.get(), &C::method, std::move(a1)); \ 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 { \ - MethodCall4 call(c_.get(), &C::method, a1, a2, a3, \ - a4); \ - return call.Marshal(RTC_FROM_HERE, signaling_thread_); \ +#define PROXY_METHOD2(r, method, t1, t2) \ + r method(t1 a1, t2 a2) override { \ + MethodCall2 call(c_.get(), &C::method, std::move(a1), \ + std::move(a2)); \ + 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 { \ - MethodCall5 call(c_.get(), &C::method, a1, a2, \ - a3, a4, a5); \ - 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 { \ + MethodCall3 call(c_.get(), &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 { \ + MethodCall4 call(c_.get(), &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 { \ + MethodCall5 call( \ + c_.get(), &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_METHOD1(r, method, t1) \ - r method(t1 a1) override { \ - MethodCall1 call(c_.get(), &C::method, a1); \ - return call.Marshal(RTC_FROM_HERE, worker_thread_); \ +#define PROXY_WORKER_METHOD0(r, method) \ + r method() override { \ + MethodCall0 call(c_.get(), &C::method); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ } -#define PROXY_WORKER_METHOD2(r, method, t1, t2) \ - r method(t1 a1, t2 a2) override { \ - MethodCall2 call(c_.get(), &C::method, a1, a2); \ - return call.Marshal(RTC_FROM_HERE, worker_thread_); \ +#define PROXY_WORKER_CONSTMETHOD0(r, method) \ + r method() const override { \ + ConstMethodCall0 call(c_.get(), &C::method); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ } -#define END_SIGNALING_PROXY() \ - private: \ - void Release_s() { c_ = NULL; } \ - mutable rtc::Thread* signaling_thread_; \ - rtc::scoped_refptr c_; \ - } \ - ; +#define PROXY_WORKER_METHOD1(r, method, t1) \ + r method(t1 a1) override { \ + MethodCall1 call(c_.get(), &C::method, std::move(a1)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } -#define END_PROXY() \ - private: \ - void Release_s() { c_ = NULL; } \ - mutable rtc::Thread* signaling_thread_; \ - mutable rtc::Thread* worker_thread_; \ - rtc::scoped_refptr c_; \ - } \ +#define PROXY_WORKER_CONSTMETHOD1(r, method, t1) \ + r method(t1 a1) const override { \ + ConstMethodCall1 call(c_.get(), &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 { \ + MethodCall2 call(c_.get(), &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 { \ + ConstMethodCall2 call(c_.get(), &C::method, std::move(a1), \ + std::move(a2)); \ + return call.Marshal(RTC_FROM_HERE, worker_thread_); \ + } + +#define END_PROXY_MAP() \ + } \ ; } // namespace webrtc diff --git a/webrtc/api/proxy_unittest.cc b/webrtc/api/proxy_unittest.cc index 193fb298a2..148b74210e 100644 --- a/webrtc/api/proxy_unittest.cc +++ b/webrtc/api/proxy_unittest.cc @@ -37,7 +37,7 @@ class FakeInterface : public rtc::RefCountInterface { virtual std::string Method2(std::string s1, std::string s2) = 0; protected: - ~FakeInterface() {} + virtual ~FakeInterface() {} }; // Implementation of the test interface. @@ -46,6 +46,8 @@ class Fake : public FakeInterface { static rtc::scoped_refptr Create() { return new rtc::RefCountedObject(); } + // Used to verify destructor is called on the correct thread. + MOCK_METHOD0(Destroy, void()); MOCK_METHOD0(VoidMethod0, void()); MOCK_METHOD0(Method0, std::string()); @@ -58,30 +60,32 @@ class Fake : public FakeInterface { protected: Fake() {} - ~Fake() {} + ~Fake() { Destroy(); } }; // Proxies for the test interface. BEGIN_PROXY_MAP(Fake) + PROXY_WORKER_THREAD_DESTRUCTOR() PROXY_METHOD0(void, VoidMethod0) PROXY_METHOD0(std::string, Method0) PROXY_CONSTMETHOD0(std::string, ConstMethod0) PROXY_WORKER_METHOD1(std::string, Method1, std::string) PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string) PROXY_WORKER_METHOD2(std::string, Method2, std::string, std::string) -END_PROXY() +END_PROXY_MAP() // Preprocessor hack to get a proxy class a name different than FakeProxy. #define FakeProxy FakeSignalingProxy #define FakeProxyWithInternal FakeSignalingProxyWithInternal BEGIN_SIGNALING_PROXY_MAP(Fake) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_METHOD0(void, VoidMethod0) PROXY_METHOD0(std::string, Method0) PROXY_CONSTMETHOD0(std::string, ConstMethod0) PROXY_METHOD1(std::string, Method1, std::string) PROXY_CONSTMETHOD1(std::string, ConstMethod1, std::string) PROXY_METHOD2(std::string, Method2, std::string, std::string) -END_SIGNALING_PROXY() +END_PROXY_MAP() #undef FakeProxy class SignalingProxyTest : public testing::Test { @@ -104,6 +108,15 @@ class SignalingProxyTest : public testing::Test { rtc::scoped_refptr fake_; }; +TEST_F(SignalingProxyTest, SignalingThreadDestructor) { + EXPECT_CALL(*fake_, Destroy()) + .Times(Exactly(1)) + .WillOnce( + InvokeWithoutArgs(this, &SignalingProxyTest::CheckSignalingThread)); + fake_ = nullptr; + fake_signaling_proxy_ = nullptr; +} + TEST_F(SignalingProxyTest, VoidMethod0) { EXPECT_CALL(*fake_, VoidMethod0()) .Times(Exactly(1)) @@ -161,25 +174,38 @@ TEST_F(SignalingProxyTest, Method2) { EXPECT_EQ("Method2", fake_signaling_proxy_->Method2(arg1, arg2)); } -class ProxyTest : public SignalingProxyTest { +class ProxyTest : public testing::Test { public: // Checks that the functions are called on the right thread. + void CheckSignalingThread() { EXPECT_TRUE(signaling_thread_->IsCurrent()); } void CheckWorkerThread() { EXPECT_TRUE(worker_thread_->IsCurrent()); } protected: void SetUp() override { - SignalingProxyTest::SetUp(); + signaling_thread_.reset(new rtc::Thread()); worker_thread_.reset(new rtc::Thread()); + ASSERT_TRUE(signaling_thread_->Start()); ASSERT_TRUE(worker_thread_->Start()); + fake_ = Fake::Create(); fake_proxy_ = FakeProxy::Create(signaling_thread_.get(), worker_thread_.get(), fake_.get()); } protected: + std::unique_ptr signaling_thread_; std::unique_ptr worker_thread_; rtc::scoped_refptr fake_proxy_; + rtc::scoped_refptr fake_; }; +TEST_F(ProxyTest, WorkerThreadDestructor) { + EXPECT_CALL(*fake_, Destroy()) + .Times(Exactly(1)) + .WillOnce(InvokeWithoutArgs(this, &ProxyTest::CheckWorkerThread)); + fake_ = nullptr; + fake_proxy_ = nullptr; +} + TEST_F(ProxyTest, VoidMethod0) { EXPECT_CALL(*fake_, VoidMethod0()) .Times(Exactly(1)) @@ -236,4 +262,51 @@ TEST_F(ProxyTest, WorkerMethod2) { EXPECT_EQ("Method2", fake_proxy_->Method2(arg1, arg2)); } +// Interface for testing OWNED_PROXY_MAP. +class FooInterface { + public: + virtual ~FooInterface() {} + virtual void Bar() = 0; +}; + +class Foo : public FooInterface { + public: + Foo() {} + MOCK_METHOD0(Bar, void()); +}; + +BEGIN_OWNED_PROXY_MAP(Foo) + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_METHOD0(void, Bar) +END_PROXY_MAP() + +class OwnedProxyTest : public testing::Test { + public: + OwnedProxyTest() + : foo_(new Foo()), + foo_proxy_( + FooProxy::Create(&signaling_thread_, &worker_thread_, foo_)) { + signaling_thread_.Start(); + worker_thread_.Start(); + } + + void CheckSignalingThread() { EXPECT_TRUE(signaling_thread_.IsCurrent()); } + void CheckWorkerThread() { EXPECT_TRUE(worker_thread_.IsCurrent()); } + + protected: + rtc::Thread signaling_thread_; + rtc::Thread worker_thread_; + Foo* foo_; // Owned by foo_proxy_, not this class. + std::unique_ptr foo_proxy_; +}; + +// Just tests that a method can be invoked using an "owned proxy" (as opposed +// to normal ref-counted version). +TEST_F(OwnedProxyTest, BasicTest) { + EXPECT_CALL(*foo_, Bar()) + .Times(Exactly(1)) + .WillOnce(InvokeWithoutArgs(this, &OwnedProxyTest::CheckSignalingThread)); + foo_proxy_->Bar(); +} + } // namespace webrtc diff --git a/webrtc/api/rtpreceiverinterface.h b/webrtc/api/rtpreceiverinterface.h index 53a37398cf..103df473e3 100644 --- a/webrtc/api/rtpreceiverinterface.h +++ b/webrtc/api/rtpreceiverinterface.h @@ -66,13 +66,14 @@ class RtpReceiverInterface : public rtc::RefCountInterface { // Define proxy for RtpReceiverInterface. BEGIN_SIGNALING_PROXY_MAP(RtpReceiver) -PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) -PROXY_CONSTMETHOD0(cricket::MediaType, media_type) -PROXY_CONSTMETHOD0(std::string, id) -PROXY_CONSTMETHOD0(RtpParameters, GetParameters); -PROXY_METHOD1(bool, SetParameters, const RtpParameters&) -PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*); -END_SIGNALING_PROXY() + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) + PROXY_CONSTMETHOD0(cricket::MediaType, media_type) + PROXY_CONSTMETHOD0(std::string, id) + PROXY_CONSTMETHOD0(RtpParameters, GetParameters); + PROXY_METHOD1(bool, SetParameters, const RtpParameters&) + PROXY_METHOD1(void, SetObserver, RtpReceiverObserverInterface*); +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/rtpsenderinterface.h b/webrtc/api/rtpsenderinterface.h index c940dc7c09..2e6b7427a1 100644 --- a/webrtc/api/rtpsenderinterface.h +++ b/webrtc/api/rtpsenderinterface.h @@ -57,15 +57,16 @@ class RtpSenderInterface : public rtc::RefCountInterface { // Define proxy for RtpSenderInterface. BEGIN_SIGNALING_PROXY_MAP(RtpSender) -PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*) -PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) -PROXY_CONSTMETHOD0(uint32_t, ssrc) -PROXY_CONSTMETHOD0(cricket::MediaType, media_type) -PROXY_CONSTMETHOD0(std::string, id) -PROXY_CONSTMETHOD0(std::vector, stream_ids) -PROXY_CONSTMETHOD0(RtpParameters, GetParameters); -PROXY_METHOD1(bool, SetParameters, const RtpParameters&) -END_SIGNALING_PROXY() + PROXY_SIGNALING_THREAD_DESTRUCTOR() + PROXY_METHOD1(bool, SetTrack, MediaStreamTrackInterface*) + PROXY_CONSTMETHOD0(rtc::scoped_refptr, track) + PROXY_CONSTMETHOD0(uint32_t, ssrc) + PROXY_CONSTMETHOD0(cricket::MediaType, media_type) + PROXY_CONSTMETHOD0(std::string, id) + PROXY_CONSTMETHOD0(std::vector, stream_ids) + PROXY_CONSTMETHOD0(RtpParameters, GetParameters); + PROXY_METHOD1(bool, SetParameters, const RtpParameters&) +END_PROXY_MAP() } // namespace webrtc diff --git a/webrtc/api/videosourceproxy.h b/webrtc/api/videosourceproxy.h index eaec17bbb1..b678acb070 100644 --- a/webrtc/api/videosourceproxy.h +++ b/webrtc/api/videosourceproxy.h @@ -21,6 +21,7 @@ namespace webrtc { // destroyed on the signaling thread and marshals all method calls to the // signaling thread. BEGIN_PROXY_MAP(VideoTrackSource) + PROXY_SIGNALING_THREAD_DESTRUCTOR() PROXY_CONSTMETHOD0(SourceState, state) PROXY_CONSTMETHOD0(bool, remote) PROXY_CONSTMETHOD0(bool, is_screencast) @@ -33,7 +34,7 @@ BEGIN_PROXY_MAP(VideoTrackSource) PROXY_WORKER_METHOD1(void, RemoveSink, rtc::VideoSinkInterface*) PROXY_METHOD1(void, RegisterObserver, ObserverInterface*) PROXY_METHOD1(void, UnregisterObserver, ObserverInterface*) -END_PROXY() +END_PROXY_MAP() } // namespace webrtc