1*6777b538SAndroid Build Coastguard Worker // Copyright 2012 The Chromium Authors
2*6777b538SAndroid Build Coastguard Worker // Use of this source code is governed by a BSD-style license that can be
3*6777b538SAndroid Build Coastguard Worker // found in the LICENSE file.
4*6777b538SAndroid Build Coastguard Worker
5*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread.h"
6*6777b538SAndroid Build Coastguard Worker
7*6777b538SAndroid Build Coastguard Worker #include <memory>
8*6777b538SAndroid Build Coastguard Worker #include <type_traits>
9*6777b538SAndroid Build Coastguard Worker #include <utility>
10*6777b538SAndroid Build Coastguard Worker
11*6777b538SAndroid Build Coastguard Worker #include "base/dcheck_is_on.h"
12*6777b538SAndroid Build Coastguard Worker #include "base/functional/bind.h"
13*6777b538SAndroid Build Coastguard Worker #include "base/functional/callback_helpers.h"
14*6777b538SAndroid Build Coastguard Worker #include "base/location.h"
15*6777b538SAndroid Build Coastguard Worker #include "base/logging.h"
16*6777b538SAndroid Build Coastguard Worker #include "base/memory/ptr_util.h"
17*6777b538SAndroid Build Coastguard Worker #include "base/memory/scoped_refptr.h"
18*6777b538SAndroid Build Coastguard Worker #include "base/message_loop/message_pump.h"
19*6777b538SAndroid Build Coastguard Worker #include "base/run_loop.h"
20*6777b538SAndroid Build Coastguard Worker #include "base/synchronization/waitable_event.h"
21*6777b538SAndroid Build Coastguard Worker #include "base/task/current_thread.h"
22*6777b538SAndroid Build Coastguard Worker #include "base/task/sequence_manager/sequence_manager_impl.h"
23*6777b538SAndroid Build Coastguard Worker #include "base/task/sequence_manager/task_queue.h"
24*6777b538SAndroid Build Coastguard Worker #include "base/task/single_thread_task_runner.h"
25*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_id_name_manager.h"
26*6777b538SAndroid Build Coastguard Worker #include "base/threading/thread_restrictions.h"
27*6777b538SAndroid Build Coastguard Worker #include "base/types/pass_key.h"
28*6777b538SAndroid Build Coastguard Worker #include "build/build_config.h"
29*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/base/attributes.h"
30*6777b538SAndroid Build Coastguard Worker #include "third_party/abseil-cpp/absl/base/dynamic_annotations.h"
31*6777b538SAndroid Build Coastguard Worker
32*6777b538SAndroid Build Coastguard Worker #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
33*6777b538SAndroid Build Coastguard Worker #include <optional>
34*6777b538SAndroid Build Coastguard Worker
35*6777b538SAndroid Build Coastguard Worker #include "base/files/file_descriptor_watcher_posix.h"
36*6777b538SAndroid Build Coastguard Worker #endif
37*6777b538SAndroid Build Coastguard Worker
38*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
39*6777b538SAndroid Build Coastguard Worker #include "base/win/scoped_com_initializer.h"
40*6777b538SAndroid Build Coastguard Worker #endif
41*6777b538SAndroid Build Coastguard Worker
42*6777b538SAndroid Build Coastguard Worker namespace base {
43*6777b538SAndroid Build Coastguard Worker
44*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
45*6777b538SAndroid Build Coastguard Worker namespace {
46*6777b538SAndroid Build Coastguard Worker
47*6777b538SAndroid Build Coastguard Worker // We use this thread-local variable to record whether or not a thread exited
48*6777b538SAndroid Build Coastguard Worker // because its Stop method was called. This allows us to catch cases where
49*6777b538SAndroid Build Coastguard Worker // MessageLoop::QuitWhenIdle() is called directly, which is unexpected when
50*6777b538SAndroid Build Coastguard Worker // using a Thread to setup and run a MessageLoop.
51*6777b538SAndroid Build Coastguard Worker ABSL_CONST_INIT thread_local bool was_quit_properly = false;
52*6777b538SAndroid Build Coastguard Worker
53*6777b538SAndroid Build Coastguard Worker } // namespace
54*6777b538SAndroid Build Coastguard Worker #endif
55*6777b538SAndroid Build Coastguard Worker
56*6777b538SAndroid Build Coastguard Worker namespace internal {
57*6777b538SAndroid Build Coastguard Worker
58*6777b538SAndroid Build Coastguard Worker class SequenceManagerThreadDelegate : public Thread::Delegate {
59*6777b538SAndroid Build Coastguard Worker public:
SequenceManagerThreadDelegate(MessagePumpType message_pump_type,OnceCallback<std::unique_ptr<MessagePump> ()> message_pump_factory)60*6777b538SAndroid Build Coastguard Worker explicit SequenceManagerThreadDelegate(
61*6777b538SAndroid Build Coastguard Worker MessagePumpType message_pump_type,
62*6777b538SAndroid Build Coastguard Worker OnceCallback<std::unique_ptr<MessagePump>()> message_pump_factory)
63*6777b538SAndroid Build Coastguard Worker : sequence_manager_(
64*6777b538SAndroid Build Coastguard Worker sequence_manager::internal::CreateUnboundSequenceManagerImpl(
65*6777b538SAndroid Build Coastguard Worker PassKey<base::internal::SequenceManagerThreadDelegate>(),
66*6777b538SAndroid Build Coastguard Worker sequence_manager::SequenceManager::Settings::Builder()
67*6777b538SAndroid Build Coastguard Worker .SetMessagePumpType(message_pump_type)
68*6777b538SAndroid Build Coastguard Worker .Build())),
69*6777b538SAndroid Build Coastguard Worker default_task_queue_(sequence_manager_->CreateTaskQueue(
70*6777b538SAndroid Build Coastguard Worker sequence_manager::TaskQueue::Spec(
71*6777b538SAndroid Build Coastguard Worker sequence_manager::QueueName::DEFAULT_TQ))),
72*6777b538SAndroid Build Coastguard Worker message_pump_factory_(std::move(message_pump_factory)) {
73*6777b538SAndroid Build Coastguard Worker sequence_manager_->SetDefaultTaskRunner(default_task_queue_->task_runner());
74*6777b538SAndroid Build Coastguard Worker }
75*6777b538SAndroid Build Coastguard Worker
76*6777b538SAndroid Build Coastguard Worker ~SequenceManagerThreadDelegate() override = default;
77*6777b538SAndroid Build Coastguard Worker
GetDefaultTaskRunner()78*6777b538SAndroid Build Coastguard Worker scoped_refptr<SingleThreadTaskRunner> GetDefaultTaskRunner() override {
79*6777b538SAndroid Build Coastguard Worker // Surprisingly this might not be default_task_queue_->task_runner() which
80*6777b538SAndroid Build Coastguard Worker // we set in the constructor. The Thread::Init() method could create a
81*6777b538SAndroid Build Coastguard Worker // SequenceManager on top of the current one and call
82*6777b538SAndroid Build Coastguard Worker // SequenceManager::SetDefaultTaskRunner which would propagate the new
83*6777b538SAndroid Build Coastguard Worker // TaskRunner down to our SequenceManager. Turns out, code actually relies
84*6777b538SAndroid Build Coastguard Worker // on this and somehow relies on
85*6777b538SAndroid Build Coastguard Worker // SequenceManagerThreadDelegate::GetDefaultTaskRunner returning this new
86*6777b538SAndroid Build Coastguard Worker // TaskRunner. So instead of returning default_task_queue_->task_runner() we
87*6777b538SAndroid Build Coastguard Worker // need to query the SequenceManager for it.
88*6777b538SAndroid Build Coastguard Worker // The underlying problem here is that Subclasses of Thread can do crazy
89*6777b538SAndroid Build Coastguard Worker // stuff in Init() but they are not really in control of what happens in the
90*6777b538SAndroid Build Coastguard Worker // Thread::Delegate, as this is passed in on calling StartWithOptions which
91*6777b538SAndroid Build Coastguard Worker // could happen far away from where the Thread is created. We should
92*6777b538SAndroid Build Coastguard Worker // consider getting rid of StartWithOptions, and pass them as a constructor
93*6777b538SAndroid Build Coastguard Worker // argument instead.
94*6777b538SAndroid Build Coastguard Worker return sequence_manager_->GetTaskRunner();
95*6777b538SAndroid Build Coastguard Worker }
96*6777b538SAndroid Build Coastguard Worker
BindToCurrentThread()97*6777b538SAndroid Build Coastguard Worker void BindToCurrentThread() override {
98*6777b538SAndroid Build Coastguard Worker sequence_manager_->BindToMessagePump(
99*6777b538SAndroid Build Coastguard Worker std::move(message_pump_factory_).Run());
100*6777b538SAndroid Build Coastguard Worker }
101*6777b538SAndroid Build Coastguard Worker
102*6777b538SAndroid Build Coastguard Worker private:
103*6777b538SAndroid Build Coastguard Worker std::unique_ptr<sequence_manager::internal::SequenceManagerImpl>
104*6777b538SAndroid Build Coastguard Worker sequence_manager_;
105*6777b538SAndroid Build Coastguard Worker sequence_manager::TaskQueue::Handle default_task_queue_;
106*6777b538SAndroid Build Coastguard Worker OnceCallback<std::unique_ptr<MessagePump>()> message_pump_factory_;
107*6777b538SAndroid Build Coastguard Worker };
108*6777b538SAndroid Build Coastguard Worker
109*6777b538SAndroid Build Coastguard Worker } // namespace internal
110*6777b538SAndroid Build Coastguard Worker
111*6777b538SAndroid Build Coastguard Worker Thread::Options::Options() = default;
112*6777b538SAndroid Build Coastguard Worker
Options(MessagePumpType type,size_t size)113*6777b538SAndroid Build Coastguard Worker Thread::Options::Options(MessagePumpType type, size_t size)
114*6777b538SAndroid Build Coastguard Worker : message_pump_type(type), stack_size(size) {}
115*6777b538SAndroid Build Coastguard Worker
Options(ThreadType thread_type)116*6777b538SAndroid Build Coastguard Worker Thread::Options::Options(ThreadType thread_type) : thread_type(thread_type) {}
117*6777b538SAndroid Build Coastguard Worker
Options(Options && other)118*6777b538SAndroid Build Coastguard Worker Thread::Options::Options(Options&& other)
119*6777b538SAndroid Build Coastguard Worker : message_pump_type(std::move(other.message_pump_type)),
120*6777b538SAndroid Build Coastguard Worker delegate(std::move(other.delegate)),
121*6777b538SAndroid Build Coastguard Worker message_pump_factory(std::move(other.message_pump_factory)),
122*6777b538SAndroid Build Coastguard Worker stack_size(std::move(other.stack_size)),
123*6777b538SAndroid Build Coastguard Worker thread_type(std::move(other.thread_type)),
124*6777b538SAndroid Build Coastguard Worker joinable(std::move(other.joinable)) {
125*6777b538SAndroid Build Coastguard Worker other.moved_from = true;
126*6777b538SAndroid Build Coastguard Worker }
127*6777b538SAndroid Build Coastguard Worker
operator =(Thread::Options && other)128*6777b538SAndroid Build Coastguard Worker Thread::Options& Thread::Options::operator=(Thread::Options&& other) {
129*6777b538SAndroid Build Coastguard Worker DCHECK_NE(this, &other);
130*6777b538SAndroid Build Coastguard Worker
131*6777b538SAndroid Build Coastguard Worker message_pump_type = std::move(other.message_pump_type);
132*6777b538SAndroid Build Coastguard Worker delegate = std::move(other.delegate);
133*6777b538SAndroid Build Coastguard Worker message_pump_factory = std::move(other.message_pump_factory);
134*6777b538SAndroid Build Coastguard Worker stack_size = std::move(other.stack_size);
135*6777b538SAndroid Build Coastguard Worker thread_type = std::move(other.thread_type);
136*6777b538SAndroid Build Coastguard Worker joinable = std::move(other.joinable);
137*6777b538SAndroid Build Coastguard Worker other.moved_from = true;
138*6777b538SAndroid Build Coastguard Worker
139*6777b538SAndroid Build Coastguard Worker return *this;
140*6777b538SAndroid Build Coastguard Worker }
141*6777b538SAndroid Build Coastguard Worker
142*6777b538SAndroid Build Coastguard Worker Thread::Options::~Options() = default;
143*6777b538SAndroid Build Coastguard Worker
Thread(const std::string & name)144*6777b538SAndroid Build Coastguard Worker Thread::Thread(const std::string& name)
145*6777b538SAndroid Build Coastguard Worker : id_event_(WaitableEvent::ResetPolicy::MANUAL,
146*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED),
147*6777b538SAndroid Build Coastguard Worker name_(name),
148*6777b538SAndroid Build Coastguard Worker start_event_(WaitableEvent::ResetPolicy::MANUAL,
149*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED) {
150*6777b538SAndroid Build Coastguard Worker // Only bind the sequence on Start(): the state is constant between
151*6777b538SAndroid Build Coastguard Worker // construction and Start() and it's thus valid for Start() to be called on
152*6777b538SAndroid Build Coastguard Worker // another sequence as long as every other operation is then performed on that
153*6777b538SAndroid Build Coastguard Worker // sequence.
154*6777b538SAndroid Build Coastguard Worker owning_sequence_checker_.DetachFromSequence();
155*6777b538SAndroid Build Coastguard Worker }
156*6777b538SAndroid Build Coastguard Worker
~Thread()157*6777b538SAndroid Build Coastguard Worker Thread::~Thread() {
158*6777b538SAndroid Build Coastguard Worker Stop();
159*6777b538SAndroid Build Coastguard Worker }
160*6777b538SAndroid Build Coastguard Worker
Start()161*6777b538SAndroid Build Coastguard Worker bool Thread::Start() {
162*6777b538SAndroid Build Coastguard Worker DCHECK(owning_sequence_checker_.CalledOnValidSequence());
163*6777b538SAndroid Build Coastguard Worker
164*6777b538SAndroid Build Coastguard Worker Options options;
165*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
166*6777b538SAndroid Build Coastguard Worker if (com_status_ == STA)
167*6777b538SAndroid Build Coastguard Worker options.message_pump_type = MessagePumpType::UI;
168*6777b538SAndroid Build Coastguard Worker #endif
169*6777b538SAndroid Build Coastguard Worker return StartWithOptions(std::move(options));
170*6777b538SAndroid Build Coastguard Worker }
171*6777b538SAndroid Build Coastguard Worker
StartWithOptions(Options options)172*6777b538SAndroid Build Coastguard Worker bool Thread::StartWithOptions(Options options) {
173*6777b538SAndroid Build Coastguard Worker DCHECK(options.IsValid());
174*6777b538SAndroid Build Coastguard Worker DCHECK(owning_sequence_checker_.CalledOnValidSequence());
175*6777b538SAndroid Build Coastguard Worker DCHECK(!delegate_);
176*6777b538SAndroid Build Coastguard Worker DCHECK(!IsRunning());
177*6777b538SAndroid Build Coastguard Worker DCHECK(!stopping_) << "Starting a non-joinable thread a second time? That's "
178*6777b538SAndroid Build Coastguard Worker << "not allowed!";
179*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
180*6777b538SAndroid Build Coastguard Worker DCHECK((com_status_ != STA) ||
181*6777b538SAndroid Build Coastguard Worker (options.message_pump_type == MessagePumpType::UI));
182*6777b538SAndroid Build Coastguard Worker #endif
183*6777b538SAndroid Build Coastguard Worker
184*6777b538SAndroid Build Coastguard Worker // Reset |id_| here to support restarting the thread.
185*6777b538SAndroid Build Coastguard Worker id_event_.Reset();
186*6777b538SAndroid Build Coastguard Worker id_ = kInvalidThreadId;
187*6777b538SAndroid Build Coastguard Worker
188*6777b538SAndroid Build Coastguard Worker SetThreadWasQuitProperly(false);
189*6777b538SAndroid Build Coastguard Worker
190*6777b538SAndroid Build Coastguard Worker if (options.delegate) {
191*6777b538SAndroid Build Coastguard Worker DCHECK(!options.message_pump_factory);
192*6777b538SAndroid Build Coastguard Worker delegate_ = std::move(options.delegate);
193*6777b538SAndroid Build Coastguard Worker } else if (options.message_pump_factory) {
194*6777b538SAndroid Build Coastguard Worker delegate_ = std::make_unique<internal::SequenceManagerThreadDelegate>(
195*6777b538SAndroid Build Coastguard Worker MessagePumpType::CUSTOM, options.message_pump_factory);
196*6777b538SAndroid Build Coastguard Worker } else {
197*6777b538SAndroid Build Coastguard Worker delegate_ = std::make_unique<internal::SequenceManagerThreadDelegate>(
198*6777b538SAndroid Build Coastguard Worker options.message_pump_type,
199*6777b538SAndroid Build Coastguard Worker BindOnce([](MessagePumpType type) { return MessagePump::Create(type); },
200*6777b538SAndroid Build Coastguard Worker options.message_pump_type));
201*6777b538SAndroid Build Coastguard Worker }
202*6777b538SAndroid Build Coastguard Worker
203*6777b538SAndroid Build Coastguard Worker start_event_.Reset();
204*6777b538SAndroid Build Coastguard Worker
205*6777b538SAndroid Build Coastguard Worker // Hold |thread_lock_| while starting the new thread to synchronize with
206*6777b538SAndroid Build Coastguard Worker // Stop() while it's not guaranteed to be sequenced (until crbug/629139 is
207*6777b538SAndroid Build Coastguard Worker // fixed).
208*6777b538SAndroid Build Coastguard Worker {
209*6777b538SAndroid Build Coastguard Worker AutoLock lock(thread_lock_);
210*6777b538SAndroid Build Coastguard Worker bool success = options.joinable
211*6777b538SAndroid Build Coastguard Worker ? PlatformThread::CreateWithType(
212*6777b538SAndroid Build Coastguard Worker options.stack_size, this, &thread_,
213*6777b538SAndroid Build Coastguard Worker options.thread_type, options.message_pump_type)
214*6777b538SAndroid Build Coastguard Worker : PlatformThread::CreateNonJoinableWithType(
215*6777b538SAndroid Build Coastguard Worker options.stack_size, this, options.thread_type,
216*6777b538SAndroid Build Coastguard Worker options.message_pump_type);
217*6777b538SAndroid Build Coastguard Worker if (!success) {
218*6777b538SAndroid Build Coastguard Worker DLOG(ERROR) << "failed to create thread";
219*6777b538SAndroid Build Coastguard Worker return false;
220*6777b538SAndroid Build Coastguard Worker }
221*6777b538SAndroid Build Coastguard Worker }
222*6777b538SAndroid Build Coastguard Worker
223*6777b538SAndroid Build Coastguard Worker joinable_ = options.joinable;
224*6777b538SAndroid Build Coastguard Worker
225*6777b538SAndroid Build Coastguard Worker return true;
226*6777b538SAndroid Build Coastguard Worker }
227*6777b538SAndroid Build Coastguard Worker
StartAndWaitForTesting()228*6777b538SAndroid Build Coastguard Worker bool Thread::StartAndWaitForTesting() {
229*6777b538SAndroid Build Coastguard Worker DCHECK(owning_sequence_checker_.CalledOnValidSequence());
230*6777b538SAndroid Build Coastguard Worker bool result = Start();
231*6777b538SAndroid Build Coastguard Worker if (!result)
232*6777b538SAndroid Build Coastguard Worker return false;
233*6777b538SAndroid Build Coastguard Worker WaitUntilThreadStarted();
234*6777b538SAndroid Build Coastguard Worker return true;
235*6777b538SAndroid Build Coastguard Worker }
236*6777b538SAndroid Build Coastguard Worker
WaitUntilThreadStarted() const237*6777b538SAndroid Build Coastguard Worker bool Thread::WaitUntilThreadStarted() const {
238*6777b538SAndroid Build Coastguard Worker DCHECK(owning_sequence_checker_.CalledOnValidSequence());
239*6777b538SAndroid Build Coastguard Worker if (!delegate_)
240*6777b538SAndroid Build Coastguard Worker return false;
241*6777b538SAndroid Build Coastguard Worker // https://crbug.com/918039
242*6777b538SAndroid Build Coastguard Worker base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
243*6777b538SAndroid Build Coastguard Worker start_event_.Wait();
244*6777b538SAndroid Build Coastguard Worker return true;
245*6777b538SAndroid Build Coastguard Worker }
246*6777b538SAndroid Build Coastguard Worker
FlushForTesting()247*6777b538SAndroid Build Coastguard Worker void Thread::FlushForTesting() {
248*6777b538SAndroid Build Coastguard Worker DCHECK(owning_sequence_checker_.CalledOnValidSequence());
249*6777b538SAndroid Build Coastguard Worker if (!delegate_)
250*6777b538SAndroid Build Coastguard Worker return;
251*6777b538SAndroid Build Coastguard Worker
252*6777b538SAndroid Build Coastguard Worker WaitableEvent done(WaitableEvent::ResetPolicy::AUTOMATIC,
253*6777b538SAndroid Build Coastguard Worker WaitableEvent::InitialState::NOT_SIGNALED);
254*6777b538SAndroid Build Coastguard Worker task_runner()->PostTask(FROM_HERE,
255*6777b538SAndroid Build Coastguard Worker BindOnce(&WaitableEvent::Signal, Unretained(&done)));
256*6777b538SAndroid Build Coastguard Worker done.Wait();
257*6777b538SAndroid Build Coastguard Worker }
258*6777b538SAndroid Build Coastguard Worker
Stop()259*6777b538SAndroid Build Coastguard Worker void Thread::Stop() {
260*6777b538SAndroid Build Coastguard Worker DCHECK(joinable_);
261*6777b538SAndroid Build Coastguard Worker
262*6777b538SAndroid Build Coastguard Worker // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
263*6777b538SAndroid Build Coastguard Worker // enable this check, until then synchronization with Start() via
264*6777b538SAndroid Build Coastguard Worker // |thread_lock_| is required...
265*6777b538SAndroid Build Coastguard Worker // DCHECK(owning_sequence_checker_.CalledOnValidSequence());
266*6777b538SAndroid Build Coastguard Worker AutoLock lock(thread_lock_);
267*6777b538SAndroid Build Coastguard Worker
268*6777b538SAndroid Build Coastguard Worker StopSoon();
269*6777b538SAndroid Build Coastguard Worker
270*6777b538SAndroid Build Coastguard Worker // Can't join if the |thread_| is either already gone or is non-joinable.
271*6777b538SAndroid Build Coastguard Worker if (thread_.is_null())
272*6777b538SAndroid Build Coastguard Worker return;
273*6777b538SAndroid Build Coastguard Worker
274*6777b538SAndroid Build Coastguard Worker // Wait for the thread to exit.
275*6777b538SAndroid Build Coastguard Worker //
276*6777b538SAndroid Build Coastguard Worker // TODO(darin): Unfortunately, we need to keep |delegate_| around
277*6777b538SAndroid Build Coastguard Worker // until the thread exits. Some consumers are abusing the API. Make them stop.
278*6777b538SAndroid Build Coastguard Worker PlatformThread::Join(thread_);
279*6777b538SAndroid Build Coastguard Worker thread_ = base::PlatformThreadHandle();
280*6777b538SAndroid Build Coastguard Worker
281*6777b538SAndroid Build Coastguard Worker // The thread should release |delegate_| on exit (note: Join() adds
282*6777b538SAndroid Build Coastguard Worker // an implicit memory barrier and no lock is thus required for this check).
283*6777b538SAndroid Build Coastguard Worker DCHECK(!delegate_);
284*6777b538SAndroid Build Coastguard Worker
285*6777b538SAndroid Build Coastguard Worker stopping_ = false;
286*6777b538SAndroid Build Coastguard Worker }
287*6777b538SAndroid Build Coastguard Worker
StopSoon()288*6777b538SAndroid Build Coastguard Worker void Thread::StopSoon() {
289*6777b538SAndroid Build Coastguard Worker // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
290*6777b538SAndroid Build Coastguard Worker // enable this check.
291*6777b538SAndroid Build Coastguard Worker // DCHECK(owning_sequence_checker_.CalledOnValidSequence());
292*6777b538SAndroid Build Coastguard Worker
293*6777b538SAndroid Build Coastguard Worker if (stopping_ || !delegate_)
294*6777b538SAndroid Build Coastguard Worker return;
295*6777b538SAndroid Build Coastguard Worker
296*6777b538SAndroid Build Coastguard Worker stopping_ = true;
297*6777b538SAndroid Build Coastguard Worker
298*6777b538SAndroid Build Coastguard Worker task_runner()->PostTask(
299*6777b538SAndroid Build Coastguard Worker FROM_HERE, base::BindOnce(&Thread::ThreadQuitHelper, Unretained(this)));
300*6777b538SAndroid Build Coastguard Worker }
301*6777b538SAndroid Build Coastguard Worker
DetachFromSequence()302*6777b538SAndroid Build Coastguard Worker void Thread::DetachFromSequence() {
303*6777b538SAndroid Build Coastguard Worker DCHECK(owning_sequence_checker_.CalledOnValidSequence());
304*6777b538SAndroid Build Coastguard Worker owning_sequence_checker_.DetachFromSequence();
305*6777b538SAndroid Build Coastguard Worker }
306*6777b538SAndroid Build Coastguard Worker
GetThreadId() const307*6777b538SAndroid Build Coastguard Worker PlatformThreadId Thread::GetThreadId() const {
308*6777b538SAndroid Build Coastguard Worker if (!id_event_.IsSignaled()) {
309*6777b538SAndroid Build Coastguard Worker // If the thread is created but not started yet, wait for |id_| being ready.
310*6777b538SAndroid Build Coastguard Worker base::ScopedAllowBaseSyncPrimitivesOutsideBlockingScope allow_wait;
311*6777b538SAndroid Build Coastguard Worker id_event_.Wait();
312*6777b538SAndroid Build Coastguard Worker }
313*6777b538SAndroid Build Coastguard Worker return id_;
314*6777b538SAndroid Build Coastguard Worker }
315*6777b538SAndroid Build Coastguard Worker
IsRunning() const316*6777b538SAndroid Build Coastguard Worker bool Thread::IsRunning() const {
317*6777b538SAndroid Build Coastguard Worker // TODO(gab): Fix improper usage of this API (http://crbug.com/629139) and
318*6777b538SAndroid Build Coastguard Worker // enable this check.
319*6777b538SAndroid Build Coastguard Worker // DCHECK(owning_sequence_checker_.CalledOnValidSequence());
320*6777b538SAndroid Build Coastguard Worker
321*6777b538SAndroid Build Coastguard Worker // If the thread's already started (i.e. |delegate_| is non-null) and
322*6777b538SAndroid Build Coastguard Worker // not yet requested to stop (i.e. |stopping_| is false) we can just return
323*6777b538SAndroid Build Coastguard Worker // true. (Note that |stopping_| is touched only on the same sequence that
324*6777b538SAndroid Build Coastguard Worker // starts / started the new thread so we need no locking here.)
325*6777b538SAndroid Build Coastguard Worker if (delegate_ && !stopping_)
326*6777b538SAndroid Build Coastguard Worker return true;
327*6777b538SAndroid Build Coastguard Worker // Otherwise check the |running_| flag, which is set to true by the new thread
328*6777b538SAndroid Build Coastguard Worker // only while it is inside Run().
329*6777b538SAndroid Build Coastguard Worker AutoLock lock(running_lock_);
330*6777b538SAndroid Build Coastguard Worker return running_;
331*6777b538SAndroid Build Coastguard Worker }
332*6777b538SAndroid Build Coastguard Worker
Run(RunLoop * run_loop)333*6777b538SAndroid Build Coastguard Worker void Thread::Run(RunLoop* run_loop) {
334*6777b538SAndroid Build Coastguard Worker // Overridable protected method to be called from our |thread_| only.
335*6777b538SAndroid Build Coastguard Worker DCHECK(id_event_.IsSignaled());
336*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(id_, PlatformThread::CurrentId());
337*6777b538SAndroid Build Coastguard Worker
338*6777b538SAndroid Build Coastguard Worker run_loop->Run();
339*6777b538SAndroid Build Coastguard Worker }
340*6777b538SAndroid Build Coastguard Worker
341*6777b538SAndroid Build Coastguard Worker // static
SetThreadWasQuitProperly(bool flag)342*6777b538SAndroid Build Coastguard Worker void Thread::SetThreadWasQuitProperly(bool flag) {
343*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
344*6777b538SAndroid Build Coastguard Worker was_quit_properly = flag;
345*6777b538SAndroid Build Coastguard Worker #endif
346*6777b538SAndroid Build Coastguard Worker }
347*6777b538SAndroid Build Coastguard Worker
348*6777b538SAndroid Build Coastguard Worker // static
GetThreadWasQuitProperly()349*6777b538SAndroid Build Coastguard Worker bool Thread::GetThreadWasQuitProperly() {
350*6777b538SAndroid Build Coastguard Worker #if DCHECK_IS_ON()
351*6777b538SAndroid Build Coastguard Worker return was_quit_properly;
352*6777b538SAndroid Build Coastguard Worker #else
353*6777b538SAndroid Build Coastguard Worker return true;
354*6777b538SAndroid Build Coastguard Worker #endif
355*6777b538SAndroid Build Coastguard Worker }
356*6777b538SAndroid Build Coastguard Worker
ThreadMain()357*6777b538SAndroid Build Coastguard Worker void Thread::ThreadMain() {
358*6777b538SAndroid Build Coastguard Worker // First, make GetThreadId() available to avoid deadlocks. It could be called
359*6777b538SAndroid Build Coastguard Worker // any place in the following thread initialization code.
360*6777b538SAndroid Build Coastguard Worker DCHECK(!id_event_.IsSignaled());
361*6777b538SAndroid Build Coastguard Worker // Note: this read of |id_| while |id_event_| isn't signaled is exceptionally
362*6777b538SAndroid Build Coastguard Worker // okay because ThreadMain has a happens-after relationship with the other
363*6777b538SAndroid Build Coastguard Worker // write in StartWithOptions().
364*6777b538SAndroid Build Coastguard Worker DCHECK_EQ(kInvalidThreadId, id_);
365*6777b538SAndroid Build Coastguard Worker id_ = PlatformThread::CurrentId();
366*6777b538SAndroid Build Coastguard Worker DCHECK_NE(kInvalidThreadId, id_);
367*6777b538SAndroid Build Coastguard Worker id_event_.Signal();
368*6777b538SAndroid Build Coastguard Worker
369*6777b538SAndroid Build Coastguard Worker // Complete the initialization of our Thread object.
370*6777b538SAndroid Build Coastguard Worker PlatformThread::SetName(name_.c_str());
371*6777b538SAndroid Build Coastguard Worker ABSL_ANNOTATE_THREAD_NAME(name_.c_str()); // Tell the name to race detector.
372*6777b538SAndroid Build Coastguard Worker
373*6777b538SAndroid Build Coastguard Worker // Lazily initialize the |message_loop| so that it can run on this thread.
374*6777b538SAndroid Build Coastguard Worker DCHECK(delegate_);
375*6777b538SAndroid Build Coastguard Worker // This binds CurrentThread and SingleThreadTaskRunner::CurrentDefaultHandle.
376*6777b538SAndroid Build Coastguard Worker delegate_->BindToCurrentThread();
377*6777b538SAndroid Build Coastguard Worker DCHECK(CurrentThread::Get());
378*6777b538SAndroid Build Coastguard Worker DCHECK(SingleThreadTaskRunner::HasCurrentDefault());
379*6777b538SAndroid Build Coastguard Worker #if (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
380*6777b538SAndroid Build Coastguard Worker // Allow threads running a MessageLoopForIO to use FileDescriptorWatcher API.
381*6777b538SAndroid Build Coastguard Worker std::unique_ptr<FileDescriptorWatcher> file_descriptor_watcher;
382*6777b538SAndroid Build Coastguard Worker if (CurrentIOThread::IsSet()) {
383*6777b538SAndroid Build Coastguard Worker file_descriptor_watcher = std::make_unique<FileDescriptorWatcher>(
384*6777b538SAndroid Build Coastguard Worker delegate_->GetDefaultTaskRunner());
385*6777b538SAndroid Build Coastguard Worker }
386*6777b538SAndroid Build Coastguard Worker #endif // (BUILDFLAG(IS_POSIX) && !BUILDFLAG(IS_NACL)) || BUILDFLAG(IS_FUCHSIA)
387*6777b538SAndroid Build Coastguard Worker
388*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
389*6777b538SAndroid Build Coastguard Worker std::unique_ptr<win::ScopedCOMInitializer> com_initializer;
390*6777b538SAndroid Build Coastguard Worker if (com_status_ != NONE) {
391*6777b538SAndroid Build Coastguard Worker com_initializer.reset(
392*6777b538SAndroid Build Coastguard Worker (com_status_ == STA)
393*6777b538SAndroid Build Coastguard Worker ? new win::ScopedCOMInitializer()
394*6777b538SAndroid Build Coastguard Worker : new win::ScopedCOMInitializer(win::ScopedCOMInitializer::kMTA));
395*6777b538SAndroid Build Coastguard Worker }
396*6777b538SAndroid Build Coastguard Worker #endif
397*6777b538SAndroid Build Coastguard Worker
398*6777b538SAndroid Build Coastguard Worker // Let the thread do extra initialization.
399*6777b538SAndroid Build Coastguard Worker Init();
400*6777b538SAndroid Build Coastguard Worker
401*6777b538SAndroid Build Coastguard Worker {
402*6777b538SAndroid Build Coastguard Worker AutoLock lock(running_lock_);
403*6777b538SAndroid Build Coastguard Worker running_ = true;
404*6777b538SAndroid Build Coastguard Worker }
405*6777b538SAndroid Build Coastguard Worker
406*6777b538SAndroid Build Coastguard Worker start_event_.Signal();
407*6777b538SAndroid Build Coastguard Worker
408*6777b538SAndroid Build Coastguard Worker RunLoop run_loop;
409*6777b538SAndroid Build Coastguard Worker run_loop_ = &run_loop;
410*6777b538SAndroid Build Coastguard Worker Run(run_loop_);
411*6777b538SAndroid Build Coastguard Worker
412*6777b538SAndroid Build Coastguard Worker {
413*6777b538SAndroid Build Coastguard Worker AutoLock lock(running_lock_);
414*6777b538SAndroid Build Coastguard Worker running_ = false;
415*6777b538SAndroid Build Coastguard Worker }
416*6777b538SAndroid Build Coastguard Worker
417*6777b538SAndroid Build Coastguard Worker // Let the thread do extra cleanup.
418*6777b538SAndroid Build Coastguard Worker CleanUp();
419*6777b538SAndroid Build Coastguard Worker
420*6777b538SAndroid Build Coastguard Worker #if BUILDFLAG(IS_WIN)
421*6777b538SAndroid Build Coastguard Worker com_initializer.reset();
422*6777b538SAndroid Build Coastguard Worker #endif
423*6777b538SAndroid Build Coastguard Worker
424*6777b538SAndroid Build Coastguard Worker DCHECK(GetThreadWasQuitProperly());
425*6777b538SAndroid Build Coastguard Worker
426*6777b538SAndroid Build Coastguard Worker // We can't receive messages anymore.
427*6777b538SAndroid Build Coastguard Worker // (The message loop is destructed at the end of this block)
428*6777b538SAndroid Build Coastguard Worker delegate_.reset();
429*6777b538SAndroid Build Coastguard Worker run_loop_ = nullptr;
430*6777b538SAndroid Build Coastguard Worker }
431*6777b538SAndroid Build Coastguard Worker
ThreadQuitHelper()432*6777b538SAndroid Build Coastguard Worker void Thread::ThreadQuitHelper() {
433*6777b538SAndroid Build Coastguard Worker DCHECK(run_loop_);
434*6777b538SAndroid Build Coastguard Worker run_loop_->QuitWhenIdle();
435*6777b538SAndroid Build Coastguard Worker SetThreadWasQuitProperly(true);
436*6777b538SAndroid Build Coastguard Worker }
437*6777b538SAndroid Build Coastguard Worker
438*6777b538SAndroid Build Coastguard Worker } // namespace base
439