Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(470)

Side by Side Diff: base/threading/thread.cc

Issue 2135413003: Add |joinable| to Thread::Options (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: fix compile Created 4 years, 5 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « base/threading/thread.h ('k') | base/threading/thread_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. 1 // Copyright (c) 2012 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be 2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file. 3 // found in the LICENSE file.
4 4
5 #include "base/threading/thread.h" 5 #include "base/threading/thread.h"
6 6
7 #include "base/bind.h" 7 #include "base/bind.h"
8 #include "base/bind_helpers.h" 8 #include "base/bind_helpers.h"
9 #include "base/lazy_instance.h" 9 #include "base/lazy_instance.h"
10 #include "base/location.h" 10 #include "base/location.h"
(...skipping 10 matching lines...) Expand all
21 #endif 21 #endif
22 22
23 namespace base { 23 namespace base {
24 24
25 namespace { 25 namespace {
26 26
27 // We use this thread-local variable to record whether or not a thread exited 27 // We use this thread-local variable to record whether or not a thread exited
28 // because its Stop method was called. This allows us to catch cases where 28 // because its Stop method was called. This allows us to catch cases where
29 // MessageLoop::QuitWhenIdle() is called directly, which is unexpected when 29 // MessageLoop::QuitWhenIdle() is called directly, which is unexpected when
30 // using a Thread to setup and run a MessageLoop. 30 // using a Thread to setup and run a MessageLoop.
31 base::LazyInstance<base::ThreadLocalBoolean> lazy_tls_bool = 31 base::LazyInstance<base::ThreadLocalBoolean>::Leaky lazy_tls_bool =
32 LAZY_INSTANCE_INITIALIZER; 32 LAZY_INSTANCE_INITIALIZER;
33 33
34 } // namespace 34 } // namespace
35 35
36 Thread::Options::Options() = default; 36 Thread::Options::Options() = default;
37 37
38 Thread::Options::Options(MessageLoop::Type type, size_t size) 38 Thread::Options::Options(MessageLoop::Type type, size_t size)
39 : message_loop_type(type), stack_size(size) {} 39 : message_loop_type(type), stack_size(size) {}
40 40
41 Thread::Options::Options(const Options& other) = default; 41 Thread::Options::Options(const Options& other) = default;
(...skipping 25 matching lines...) Expand all
67 if (com_status_ == STA) 67 if (com_status_ == STA)
68 options.message_loop_type = MessageLoop::TYPE_UI; 68 options.message_loop_type = MessageLoop::TYPE_UI;
69 #endif 69 #endif
70 return StartWithOptions(options); 70 return StartWithOptions(options);
71 } 71 }
72 72
73 bool Thread::StartWithOptions(const Options& options) { 73 bool Thread::StartWithOptions(const Options& options) {
74 DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread()); 74 DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
75 DCHECK(!message_loop_); 75 DCHECK(!message_loop_);
76 DCHECK(!IsRunning()); 76 DCHECK(!IsRunning());
77 DCHECK(!stopping_) << "Starting a non-joinable thread a second time? That's "
78 << "not allowed!";
77 #if defined(OS_WIN) 79 #if defined(OS_WIN)
78 DCHECK((com_status_ != STA) || 80 DCHECK((com_status_ != STA) ||
79 (options.message_loop_type == MessageLoop::TYPE_UI)); 81 (options.message_loop_type == MessageLoop::TYPE_UI));
80 #endif 82 #endif
81 83
82 // Reset |id_| here to support restarting the thread. 84 // Reset |id_| here to support restarting the thread.
83 id_event_.Reset(); 85 id_event_.Reset();
84 id_ = kInvalidThreadId; 86 id_ = kInvalidThreadId;
85 87
86 SetThreadWasQuitProperly(false); 88 SetThreadWasQuitProperly(false);
87 89
88 MessageLoop::Type type = options.message_loop_type; 90 MessageLoop::Type type = options.message_loop_type;
89 if (!options.message_pump_factory.is_null()) 91 if (!options.message_pump_factory.is_null())
90 type = MessageLoop::TYPE_CUSTOM; 92 type = MessageLoop::TYPE_CUSTOM;
91 93
92 message_loop_timer_slack_ = options.timer_slack; 94 message_loop_timer_slack_ = options.timer_slack;
93 std::unique_ptr<MessageLoop> message_loop_owned = 95 std::unique_ptr<MessageLoop> message_loop_owned =
94 MessageLoop::CreateUnbound(type, options.message_pump_factory); 96 MessageLoop::CreateUnbound(type, options.message_pump_factory);
95 message_loop_ = message_loop_owned.get(); 97 message_loop_ = message_loop_owned.get();
96 start_event_.Reset(); 98 start_event_.Reset();
97 99
98 // Hold |thread_lock_| while starting the new thread to synchronize with 100 // Hold |thread_lock_| while starting the new thread to synchronize with
99 // Stop() while it's not guaranteed to be sequenced (until crbug/629139 is 101 // Stop() while it's not guaranteed to be sequenced (until crbug/629139 is
100 // fixed). 102 // fixed).
101 { 103 {
102 AutoLock lock(thread_lock_); 104 AutoLock lock(thread_lock_);
103 if (!PlatformThread::CreateWithPriority(options.stack_size, this, &thread_, 105 bool success =
104 options.priority)) { 106 options.joinable
107 ? PlatformThread::CreateWithPriority(options.stack_size, this,
108 &thread_, options.priority)
109 : PlatformThread::CreateNonJoinableWithPriority(
110 options.stack_size, this, options.priority);
111 if (!success) {
105 DLOG(ERROR) << "failed to create thread"; 112 DLOG(ERROR) << "failed to create thread";
106 message_loop_ = nullptr; 113 message_loop_ = nullptr;
107 return false; 114 return false;
108 } 115 }
109 } 116 }
110 117
111 // The ownership of |message_loop_| is managed by the newly created thread 118 // The ownership of |message_loop_| is managed by the newly created thread
112 // within the ThreadMain. 119 // within the ThreadMain.
113 ignore_result(message_loop_owned.release()); 120 ignore_result(message_loop_owned.release());
114 121
(...skipping 19 matching lines...) Expand all
134 return true; 141 return true;
135 } 142 }
136 143
137 void Thread::Stop() { 144 void Thread::Stop() {
138 // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and 145 // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
139 // enable this check, until then synchronization with Start() via 146 // enable this check, until then synchronization with Start() via
140 // |thread_lock_| is required... 147 // |thread_lock_| is required...
141 // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread()); 148 // DCHECK(owning_sequence_checker_.CalledOnValidSequencedThread());
142 AutoLock lock(thread_lock_); 149 AutoLock lock(thread_lock_);
143 150
151 StopSoon();
gab 2016/07/25 21:09:00 Note: this is causing try job failures in unittest
152
153 // Can't join if the |thread_| is either already gone or is non-joinable.
144 if (thread_.is_null()) 154 if (thread_.is_null())
145 return; 155 return;
146 156
147 StopSoon();
148
149 // Wait for the thread to exit. 157 // Wait for the thread to exit.
150 // 158 //
151 // TODO(darin): Unfortunately, we need to keep |message_loop_| around until 159 // TODO(darin): Unfortunately, we need to keep |message_loop_| around until
152 // the thread exits. Some consumers are abusing the API. Make them stop. 160 // the thread exits. Some consumers are abusing the API. Make them stop.
153 // 161 //
154 PlatformThread::Join(thread_); 162 PlatformThread::Join(thread_);
155 thread_ = base::PlatformThreadHandle(); 163 thread_ = base::PlatformThreadHandle();
156 164
157 // The thread should nullify |message_loop_| on exit (note: Join() adds an 165 // The thread should nullify |message_loop_| on exit (note: Join() adds an
158 // implicit memory barrier and no lock is thus required for this check). 166 // implicit memory barrier and no lock is thus required for this check).
(...skipping 125 matching lines...) Expand 10 before | Expand all | Expand 10 after
284 run_loop_ = nullptr; 292 run_loop_ = nullptr;
285 } 293 }
286 294
287 void Thread::ThreadQuitHelper() { 295 void Thread::ThreadQuitHelper() {
288 DCHECK(run_loop_); 296 DCHECK(run_loop_);
289 run_loop_->QuitWhenIdle(); 297 run_loop_->QuitWhenIdle();
290 SetThreadWasQuitProperly(true); 298 SetThreadWasQuitProperly(true);
291 } 299 }
292 300
293 } // namespace base 301 } // namespace base
OLDNEW
« no previous file with comments | « base/threading/thread.h ('k') | base/threading/thread_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698