diff options
author | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 11:38:45 +0200 |
---|---|---|
committer | Allan Sandfeld Jensen <allan.jensen@theqtcompany.com> | 2015-08-14 17:16:47 +0000 |
commit | 3a97ca8dd9b96b599ae2d33e40df0dd2f7ea5859 (patch) | |
tree | 43cc572ba067417c7341db81f71ae7cc6e0fcc3e /chromium/base/threading/thread.cc | |
parent | f61ab1ac7f855cd281809255c0aedbb1895e1823 (diff) |
BASELINE: Update chromium to 45.0.2454.40
Change-Id: Id2121d9f11a8fc633677236c65a3e41feef589e4
Reviewed-by: Andras Becsi <andras.becsi@theqtcompany.com>
Diffstat (limited to 'chromium/base/threading/thread.cc')
-rw-r--r-- | chromium/base/threading/thread.cc | 195 |
1 files changed, 106 insertions, 89 deletions
diff --git a/chromium/base/threading/thread.cc b/chromium/base/threading/thread.cc index 0e4aab2c354..7bff24232e2 100644 --- a/chromium/base/threading/thread.cc +++ b/chromium/base/threading/thread.cc @@ -7,7 +7,6 @@ #include "base/bind.h" #include "base/lazy_instance.h" #include "base/location.h" -#include "base/profiler/scoped_tracker.h" #include "base/synchronization/waitable_event.h" #include "base/third_party/dynamic_annotations/dynamic_annotations.h" #include "base/threading/thread_id_name_manager.h" @@ -37,31 +36,19 @@ void ThreadQuitHelper() { Thread::SetThreadWasQuitProperly(true); } -// Used to pass data to ThreadMain. This structure is allocated on the stack -// from within StartWithOptions. -struct Thread::StartupData { - // We get away with a const reference here because of how we are allocated. - const Thread::Options& options; - - // Used to synchronize thread startup. - WaitableEvent event; - - explicit StartupData(const Options& opt) - : options(opt), - event(false, false) {} -}; - Thread::Options::Options() : message_loop_type(MessageLoop::TYPE_DEFAULT), timer_slack(TIMER_SLACK_NONE), - stack_size(0) { + stack_size(0), + priority(ThreadPriority::NORMAL) { } Thread::Options::Options(MessageLoop::Type type, size_t size) : message_loop_type(type), timer_slack(TIMER_SLACK_NONE), - stack_size(size) { + stack_size(size), + priority(ThreadPriority::NORMAL) { } Thread::Options::~Options() { @@ -72,13 +59,11 @@ Thread::Thread(const std::string& name) #if defined(OS_WIN) com_status_(NONE), #endif - started_(false), stopping_(false), running_(false), - startup_data_(NULL), thread_(0), - message_loop_(NULL), - thread_id_(kInvalidThreadId), + message_loop_(nullptr), + message_loop_timer_slack_(TIMER_SLACK_NONE), name_(name) { } @@ -104,34 +89,61 @@ bool Thread::StartWithOptions(const Options& options) { SetThreadWasQuitProperly(false); - StartupData startup_data(options); - startup_data_ = &startup_data; + MessageLoop::Type type = options.message_loop_type; + if (!options.message_pump_factory.is_null()) + type = MessageLoop::TYPE_CUSTOM; - if (!PlatformThread::Create(options.stack_size, this, &thread_)) { - DLOG(ERROR) << "failed to create thread"; - startup_data_ = NULL; - return false; + message_loop_timer_slack_ = options.timer_slack; + scoped_ptr<MessageLoop> message_loop = MessageLoop::CreateUnbound( + type, options.message_pump_factory); + message_loop_ = message_loop.get(); + start_event_.reset(new WaitableEvent(false, false)); + + // Hold the thread_lock_ while starting a new thread, so that we can make sure + // that thread_ is populated before the newly created thread accesses it. + { + AutoLock lock(thread_lock_); + bool created; + if (options.priority == ThreadPriority::NORMAL) { + created = PlatformThread::Create(options.stack_size, this, &thread_); + } else { + created = PlatformThread::CreateWithPriority(options.stack_size, this, + &thread_, options.priority); + } + if (!created) { + DLOG(ERROR) << "failed to create thread"; + message_loop_ = nullptr; + start_event_.reset(); + return false; + } } - // TODO(kinuko): Remove once crbug.com/465458 is solved. - tracked_objects::ScopedTracker tracking_profile_wait( - FROM_HERE_WITH_EXPLICIT_FUNCTION( - "465458 base::Thread::StartWithOptions (Wait)")); + // The ownership of message_loop is managemed by the newly created thread + // within the ThreadMain. + ignore_result(message_loop.release()); - // Wait for the thread to start and initialize message_loop_ - base::ThreadRestrictions::ScopedAllowWait allow_wait; - startup_data.event.Wait(); + DCHECK(message_loop_); + return true; +} - // set it to NULL so we don't keep a pointer to some object on the stack. - startup_data_ = NULL; - started_ = true; +bool Thread::StartAndWaitForTesting() { + bool result = Start(); + if (!result) + return false; + WaitUntilThreadStarted(); + return true; +} - DCHECK(message_loop_); +bool Thread::WaitUntilThreadStarted() { + if (!start_event_) + return false; + base::ThreadRestrictions::ScopedAllowWait allow_wait; + start_event_->Wait(); return true; } void Thread::Stop() { - if (!started_) + if (!start_event_) return; StopSoon(); @@ -147,7 +159,7 @@ void Thread::Stop() { DCHECK(!message_loop_); // The thread no longer needs to be joined. - started_ = false; + start_event_.reset(); stopping_ = false; } @@ -155,9 +167,7 @@ void Thread::Stop() { void Thread::StopSoon() { // We should only be called on the same thread that started us. - // Reading thread_id_ without a lock can lead to a benign data race - // with ThreadMain, so we annotate it to stay silent under ThreadSanitizer. - DCHECK_NE(ANNOTATE_UNPROTECTED_READ(thread_id_), PlatformThread::CurrentId()); + DCHECK_NE(thread_id(), PlatformThread::CurrentId()); if (stopping_ || !message_loop_) return; @@ -166,15 +176,22 @@ void Thread::StopSoon() { task_runner()->PostTask(FROM_HERE, base::Bind(&ThreadQuitHelper)); } -bool Thread::IsRunning() const { - return running_; +PlatformThreadId Thread::thread_id() const { + AutoLock lock(thread_lock_); + return thread_.id(); } -void Thread::SetPriority(ThreadPriority priority) { - // The thread must be started (and id known) for this to be - // compatible with all platforms. - DCHECK_NE(thread_id_, kInvalidThreadId); - PlatformThread::SetThreadPriority(thread_, priority); +bool Thread::IsRunning() const { + // If the thread's already started (i.e. message_loop_ is non-null) and + // not yet requested to stop (i.e. stopping_ is false) we can just return + // true. (Note that stopping_ is touched only on the same thread that + // starts / started the new thread so we need no locking here.) + if (message_loop_ && !stopping_) + return true; + // Otherwise check the running_ flag, which is set to true by the new thread + // only while it is inside Run(). + AutoLock lock(running_lock_); + return running_; } void Thread::Run(MessageLoop* message_loop) { @@ -194,60 +211,60 @@ bool Thread::GetThreadWasQuitProperly() { } void Thread::ThreadMain() { - { - // The message loop for this thread. - // Allocated on the heap to centralize any leak reports at this line. - scoped_ptr<MessageLoop> message_loop; - if (!startup_data_->options.message_pump_factory.is_null()) { - message_loop.reset( - new MessageLoop(startup_data_->options.message_pump_factory.Run())); - } else { - message_loop.reset( - new MessageLoop(startup_data_->options.message_loop_type)); - } + // Complete the initialization of our Thread object. + PlatformThread::SetName(name_.c_str()); + ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. - // Complete the initialization of our Thread object. - thread_id_ = PlatformThread::CurrentId(); - PlatformThread::SetName(name_); - ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector. - message_loop->set_thread_name(name_); - message_loop->SetTimerSlack(startup_data_->options.timer_slack); - message_loop_ = message_loop.get(); + // Lazily initialize the message_loop so that it can run on this thread. + DCHECK(message_loop_); + scoped_ptr<MessageLoop> message_loop(message_loop_); + message_loop_->BindToCurrentThread(); + message_loop_->set_thread_name(name_); + message_loop_->SetTimerSlack(message_loop_timer_slack_); #if defined(OS_WIN) - scoped_ptr<win::ScopedCOMInitializer> com_initializer; - if (com_status_ != NONE) { - com_initializer.reset((com_status_ == STA) ? - new win::ScopedCOMInitializer() : - new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA)); - } + scoped_ptr<win::ScopedCOMInitializer> com_initializer; + if (com_status_ != NONE) { + com_initializer.reset((com_status_ == STA) ? + new win::ScopedCOMInitializer() : + new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA)); + } #endif - // Let the thread do extra initialization. - // Let's do this before signaling we are started. - Init(); + // Make sure the thread_id() returns current thread. + // (This internally acquires lock against PlatformThread::Create) + DCHECK_EQ(thread_id(), PlatformThread::CurrentId()); + + // Let the thread do extra initialization. + Init(); + { + AutoLock lock(running_lock_); running_ = true; - startup_data_->event.Signal(); - // startup_data_ can't be touched anymore since the starting thread is now - // unlocked. + } + + start_event_->Signal(); - Run(message_loop_); + Run(message_loop_); + + { + AutoLock lock(running_lock_); running_ = false; + } - // Let the thread do extra cleanup. - CleanUp(); + // Let the thread do extra cleanup. + CleanUp(); #if defined(OS_WIN) - com_initializer.reset(); + com_initializer.reset(); #endif - // Assert that MessageLoop::Quit was called by ThreadQuitHelper. - DCHECK(GetThreadWasQuitProperly()); + // Assert that MessageLoop::Quit was called by ThreadQuitHelper. + DCHECK(GetThreadWasQuitProperly()); - // We can't receive messages anymore. - message_loop_ = NULL; - } + // We can't receive messages anymore. + // (The message loop is destructed at the end of this block) + message_loop_ = NULL; } } // namespace base |