xref: /aosp_15_r20/external/cronet/base/task/thread_pool/worker_thread_semaphore.cc (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2024 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4 
5 #include "base/task/thread_pool/worker_thread_semaphore.h"
6 
7 #include "base/check_op.h"
8 #include "base/debug/alias.h"
9 #include "base/task/thread_pool/semaphore.h"
10 #include "base/task/thread_pool/task_tracker.h"
11 #include "base/task/thread_pool/worker_thread_observer.h"
12 #include "base/threading/hang_watcher.h"
13 #include "base/time/time.h"
14 #include "base/trace_event/base_tracing.h"
15 
16 namespace base::internal {
17 
TimedWait(TimeDelta timeout)18 bool WorkerThreadSemaphore::Delegate::TimedWait(TimeDelta timeout) {
19   const bool signaled = semaphore_->TimedWait(timeout);
20   timed_out_ = !signaled;
21   return signaled;
22 }
23 
Delegate(Semaphore * semaphore,AtomicFlag * join_called_for_testing)24 WorkerThreadSemaphore::Delegate::Delegate(Semaphore* semaphore,
25                                           AtomicFlag* join_called_for_testing)
26     : semaphore_(semaphore),
27       join_called_for_testing_(join_called_for_testing) {}
28 
WorkerThreadSemaphore(ThreadType thread_type_hint,std::unique_ptr<Delegate> delegate,TrackedRef<TaskTracker> task_tracker,size_t sequence_num,const CheckedLock * predecessor_lock,void * flow_terminator)29 WorkerThreadSemaphore::WorkerThreadSemaphore(
30     ThreadType thread_type_hint,
31     std::unique_ptr<Delegate> delegate,
32     TrackedRef<TaskTracker> task_tracker,
33     size_t sequence_num,
34     const CheckedLock* predecessor_lock,
35     void* flow_terminator)
36     : WorkerThread(thread_type_hint,
37                    task_tracker,
38                    sequence_num,
39                    predecessor_lock,
40                    flow_terminator),
41       delegate_(std::move(delegate)) {
42   DCHECK(delegate_);
43 }
44 
~WorkerThreadSemaphore()45 WorkerThreadSemaphore::~WorkerThreadSemaphore() {
46   Destroy();
47 }
48 
delegate()49 WorkerThreadSemaphore::Delegate* WorkerThreadSemaphore::delegate() {
50   return delegate_.get();
51 }
52 
join_called_for_testing() const53 bool WorkerThreadSemaphore::join_called_for_testing() const {
54   return delegate_->join_called_for_testing_->IsSet();
55 }
56 
JoinForTesting()57 void WorkerThreadSemaphore::JoinForTesting() {
58   // join_called_for_testing_ is shared between semaphore workers and must be
59   // set before entering this function.
60   CHECK(delegate_->join_called_for_testing_->IsSet());
61 
62   PlatformThreadHandle thread_handle;
63   {
64     CheckedAutoLock auto_lock(thread_lock_);
65 
66     if (thread_handle_.is_null()) {
67       return;
68     }
69 
70     thread_handle = thread_handle_;
71     // Reset |thread_handle_| so it isn't joined by the destructor.
72     thread_handle_ = PlatformThreadHandle();
73   }
74 
75   PlatformThread::Join(thread_handle);
76 }
77 
Cleanup()78 void WorkerThreadSemaphore::Cleanup() {
79   DCHECK(!should_exit_.IsSet());
80   should_exit_.Set();
81   // The semaphore is not signaled here (contrasted with
82   // WorkerThreadWaitableEvent), because when this is called (in
83   // GetWork/SwapProcessedTask) the worker is awake and won't sleep without
84   // checking ShouldExit().
85 }
86 
87 }  // namespace base::internal
88