From 7866cfe575e85978dba50b1c4a1877a325601fe1 Mon Sep 17 00:00:00 2001 From: nisse Date: Wed, 26 Apr 2017 01:45:31 -0700 Subject: [PATCH] Move autowrap from ThreadManager constructor to Thread::Current. This is in preparation for a WrapCurrentThread method, or AutoThread constructor, taking a socket server as argument, to eliminate the need for the MessageQueue::set_socketserver method and its lock. No intended change in behaviour; the ThreadManager constructor records the calling thread id, and autowrap is still restricted to that thread. Behavior when NO_MAIN_THREAD_WRAPPING is defined is also unchanged. Also makes the ThreadManager a singleton, with private constructor and destructor. And marks its destructor as RTC_NOTREACHED, since by the documentation for RTC_DEFINE_STATIC_LOCAL, the intention is to leak the object and never destruct it. BUG=webrtc:7501 Review-Url: https://codereview.webrtc.org/2833993003 Cr-Commit-Position: refs/heads/master@{#17879} --- webrtc/base/thread.cc | 44 ++++++++++++++++++++++-------------- webrtc/base/thread.h | 17 +++++++++----- webrtc/base/thread_darwin.mm | 11 +-------- 3 files changed, 39 insertions(+), 33 deletions(-) diff --git a/webrtc/base/thread.cc b/webrtc/base/thread.cc index b5be475fb3..9a71c1aa3f 100644 --- a/webrtc/base/thread.cc +++ b/webrtc/base/thread.cc @@ -31,23 +31,32 @@ ThreadManager* ThreadManager::Instance() { return &thread_manager; } +ThreadManager::~ThreadManager() { + // By above RTC_DEFINE_STATIC_LOCAL. + RTC_NOTREACHED() << "ThreadManager should never be destructed."; +} + // static Thread* Thread::Current() { - return ThreadManager::Instance()->CurrentThread(); + ThreadManager* manager = ThreadManager::Instance(); + Thread* thread = manager->CurrentThread(); + +#ifndef NO_MAIN_THREAD_WRAPPING + // Only autowrap the thread which instantiated the ThreadManager. + if (!thread && manager->IsMainThread()) { + thread = new Thread(); + thread->WrapCurrentWithThreadManager(manager, true); + } +#endif + + return thread; } #if defined(WEBRTC_POSIX) #if !defined(WEBRTC_MAC) ThreadManager::ThreadManager() { + main_thread_ref_ = CurrentThreadRef(); pthread_key_create(&key_, nullptr); -#ifndef NO_MAIN_THREAD_WRAPPING - WrapCurrentThread(); -#endif -} - -ThreadManager::~ThreadManager() { - UnwrapCurrentThread(); - pthread_key_delete(key_); } #endif @@ -62,15 +71,8 @@ void ThreadManager::SetCurrentThread(Thread *thread) { #if defined(WEBRTC_WIN) ThreadManager::ThreadManager() { + main_thread_ref_ = CurrentThreadRef(); key_ = TlsAlloc(); -#ifndef NO_MAIN_THREAD_WRAPPING - WrapCurrentThread(); -#endif -} - -ThreadManager::~ThreadManager() { - UnwrapCurrentThread(); - TlsFree(key_); } Thread *ThreadManager::CurrentThread() { @@ -99,6 +101,10 @@ void ThreadManager::UnwrapCurrentThread() { } } +bool ThreadManager::IsMainThread() { + return IsThreadRefEqual(CurrentThreadRef(), main_thread_ref_); +} + Thread::ScopedDisallowBlockingCalls::ScopedDisallowBlockingCalls() : thread_(Thread::Current()), previous_state_(thread_->SetAllowBlockingCalls(false)) { @@ -142,6 +148,10 @@ Thread::~Thread() { DoDestroy(); } +bool Thread::IsCurrent() const { + return ThreadManager::Instance()->CurrentThread() == this; +} + std::unique_ptr Thread::CreateWithSocketServer() { return std::unique_ptr(new Thread(SocketServer::CreateDefault())); } diff --git a/webrtc/base/thread.h b/webrtc/base/thread.h index 01c80501c8..e9bb3249ea 100644 --- a/webrtc/base/thread.h +++ b/webrtc/base/thread.h @@ -23,6 +23,7 @@ #include "webrtc/base/constructormagic.h" #include "webrtc/base/event.h" #include "webrtc/base/messagequeue.h" +#include "webrtc/base/platform_thread_types.h" #if defined(WEBRTC_WIN) #include "webrtc/base/win32.h" @@ -36,9 +37,7 @@ class ThreadManager { public: static const int kForever = -1; - ThreadManager(); - ~ThreadManager(); - + // Singleton, constructor and destructor are private. static ThreadManager* Instance(); Thread* CurrentThread(); @@ -60,7 +59,12 @@ class ThreadManager { Thread *WrapCurrentThread(); void UnwrapCurrentThread(); + bool IsMainThread(); + private: + ThreadManager(); + ~ThreadManager(); + #if defined(WEBRTC_POSIX) pthread_key_t key_; #endif @@ -69,6 +73,9 @@ class ThreadManager { DWORD key_; #endif + // The thread to potentially autowrap. + PlatformThreadRef main_thread_ref_; + RTC_DISALLOW_COPY_AND_ASSIGN(ThreadManager); }; @@ -123,9 +130,7 @@ class LOCKABLE Thread : public MessageQueue { const bool previous_state_; }; - bool IsCurrent() const { - return Current() == this; - } + bool IsCurrent() const; // Sleeps the calling thread for the specified number of milliseconds, during // which time no processing is performed. Returns false if sleeping was diff --git a/webrtc/base/thread_darwin.mm b/webrtc/base/thread_darwin.mm index 5bcc5c8c06..5f2227d839 100644 --- a/webrtc/base/thread_darwin.mm +++ b/webrtc/base/thread_darwin.mm @@ -39,22 +39,13 @@ void InitCocoaMultiThreading() { namespace rtc { ThreadManager::ThreadManager() { + main_thread_ref_ = CurrentThreadRef(); pthread_key_create(&key_, nullptr); -#ifndef NO_MAIN_THREAD_WRAPPING - WrapCurrentThread(); -#endif // This is necessary to alert the cocoa runtime of the fact that // we are running in a multithreaded environment. InitCocoaMultiThreading(); } -ThreadManager::~ThreadManager() { - @autoreleasepool { - UnwrapCurrentThread(); - pthread_key_delete(key_); - } -} - // static void* Thread::PreRun(void* pv) { ThreadInit* init = static_cast(pv);