Chromium Code Reviews| Index: base/threading/thread.cc |
| diff --git a/base/threading/thread.cc b/base/threading/thread.cc |
| index 98610a63c09875878ffceca6417d7af16980ca89..eb04765a7a027d9e831905c76072a3f18db97152 100644 |
| --- a/base/threading/thread.cc |
| +++ b/base/threading/thread.cc |
| @@ -28,7 +28,7 @@ namespace { |
| // because its Stop method was called. This allows us to catch cases where |
| // MessageLoop::QuitWhenIdle() is called directly, which is unexpected when |
| // using a Thread to setup and run a MessageLoop. |
| -base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool = |
| +base::LazyInstance<base::ThreadLocalBoolean>::Leaky lazy_tls_bool = |
| LAZY_INSTANCE_INITIALIZER; |
| } // namespace |
| @@ -74,6 +74,8 @@ bool Thread::StartWithOptions(const Options& options) { |
| DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread()); |
| DCHECK(!message_loop_); |
| DCHECK(!IsRunning()); |
| + DCHECK(!stopping_) << "Starting a non-joinable thread a second time? That's " |
| + << "not allowed!"; |
| #if defined(OS_WIN) |
| DCHECK((com_status_ != STA) || |
| (options.message_loop_type == MessageLoop::TYPE_UI)); |
| @@ -100,8 +102,13 @@ bool Thread::StartWithOptions(const Options& options) { |
| // fixed). |
| { |
| AutoLock lock(thread_lock_); |
| - if (!PlatformThread::CreateWithPriority(options.stack_size, this, &thread_, |
| - options.priority)) { |
| + bool success = |
| + options.joinable |
| + ? PlatformThread::CreateWithPriority(options.stack_size, this, |
| + &thread_, options.priority) |
| + : PlatformThread::CreateNonJoinableWithPriority( |
| + options.stack_size, this, options.priority); |
| + if (!success) { |
| DLOG(ERROR) << "failed to create thread"; |
| message_loop_ = nullptr; |
| return false; |
| @@ -141,11 +148,12 @@ void Thread::Stop() { |
| // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread()); |
| AutoLock lock(thread_lock_); |
| + StopSoon(); |
| + |
| + // Can't join if the |thread_| is either already gone or is non-joinable. |
| if (thread_.is_null()) |
| return; |
| - StopSoon(); |
| - |
| // Wait for the thread to exit. |
| // |
| // TODO(darin): Unfortunately, we need to keep |message_loop_| around until |
| @@ -170,6 +178,16 @@ void Thread::StopSoon() { |
| return; |
| stopping_ = true; |
|
danakj
2016/07/26 19:54:25
Is it not weird that Thread will leave Stop() with
gab
2016/07/26 20:25:33
For non-joinable threads? I don't think so, attemp
|
| + |
| + if (using_external_message_loop_) { |
| + // Setting |stopping_| to true above should have been sufficient for this |
| + // thread to be considered "stopped" per it having never set its |running_| |
| + // bit by lack of its own ThreadMain. |
| + DCHECK(!IsRunning()); |
| + message_loop_ = nullptr; |
| + return; |
| + } |
| + |
| task_runner()->PostTask( |
| FROM_HERE, base::Bind(&Thread::ThreadQuitHelper, Unretained(this))); |
| } |
| @@ -219,6 +237,18 @@ bool Thread::GetThreadWasQuitProperly() { |
| return quit_properly; |
| } |
| +void Thread::SetMessageLoop(MessageLoop* message_loop) { |
| + DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread()); |
| + |
| + // Setting |message_loop_| should suffice for this thread to be considered |
| + // as "running", until Stop() is invoked. |
| + DCHECK(!IsRunning()); |
| + message_loop_ = message_loop; |
| + DCHECK(IsRunning()); |
| + |
| + using_external_message_loop_ = true; |
| +} |
| + |
| void Thread::ThreadMain() { |
| // First, make GetThreadId() available to avoid deadlocks. It could be called |
| // any place in the following thread initialization code. |