xref: /aosp_15_r20/external/cronet/base/threading/thread.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
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