1 // Copyright 2016 The Chromium Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style license that can be 3 // found in the LICENSE file. 4 5 #ifndef BASE_TASK_THREAD_POOL_WORKER_THREAD_H_ 6 #define BASE_TASK_THREAD_POOL_WORKER_THREAD_H_ 7 8 #include <memory> 9 10 #include "base/base_export.h" 11 #include "base/macros.h" 12 #include "base/memory/ref_counted.h" 13 #include "base/synchronization/atomic_flag.h" 14 #include "base/synchronization/waitable_event.h" 15 #include "base/task/common/checked_lock.h" 16 #include "base/task/thread_pool/task_source.h" 17 #include "base/task/thread_pool/tracked_ref.h" 18 #include "base/thread_annotations.h" 19 #include "base/threading/platform_thread.h" 20 #include "base/time/time.h" 21 #include "build/build_config.h" 22 23 namespace base { 24 25 class WorkerThreadObserver; 26 27 namespace internal { 28 29 class TaskTracker; 30 31 // A worker that manages a single thread to run Tasks from TaskSources returned 32 // by a delegate. 33 // 34 // A WorkerThread starts out sleeping. It is woken up by a call to WakeUp(). 35 // After a wake-up, a WorkerThread runs Tasks from TaskSources returned by 36 // the GetWork() method of its delegate as long as it doesn't return nullptr. It 37 // also periodically checks with its TaskTracker whether shutdown has completed 38 // and exits when it has. 39 // 40 // This class is thread-safe. 41 class BASE_EXPORT WorkerThread : public RefCountedThreadSafe<WorkerThread>, 42 public PlatformThread::Delegate { 43 public: 44 // Labels this WorkerThread's association. This doesn't affect any logic 45 // but will add a stack frame labeling this thread for ease of stack trace 46 // identification. 47 enum class ThreadLabel { 48 POOLED, 49 SHARED, 50 DEDICATED, 51 #if defined(OS_WIN) 52 SHARED_COM, 53 DEDICATED_COM, 54 #endif // defined(OS_WIN) 55 }; 56 57 // Delegate interface for WorkerThread. All methods are called from the 58 // thread managed by the WorkerThread instance. 59 class BASE_EXPORT Delegate { 60 public: 61 virtual ~Delegate() = default; 62 63 // Returns the ThreadLabel the Delegate wants its WorkerThreads' stacks 64 // to be labeled with. 65 virtual ThreadLabel GetThreadLabel() const = 0; 66 67 // Called by |worker|'s thread when it enters its main function. 68 virtual void OnMainEntry(const WorkerThread* worker) = 0; 69 70 // Called by |worker|'s thread to get a TaskSource from which to run a Task. 71 virtual RegisteredTaskSource GetWork(WorkerThread* worker) = 0; 72 73 // Called by the WorkerThread after it ran a Task. If the Task's 74 // TaskSource should be reenqueued, it is passed to |task_source|. 75 // Otherwise, |task_source| is nullptr. 76 virtual void DidProcessTask(RegisteredTaskSource task_source) = 0; 77 78 // Called to determine how long to sleep before the next call to GetWork(). 79 // GetWork() may be called before this timeout expires if the worker's 80 // WakeUp() method is called. 81 virtual TimeDelta GetSleepTimeout() = 0; 82 83 // Called by the WorkerThread's thread to wait for work. Override this 84 // method if the thread in question needs special handling to go to sleep. 85 // |wake_up_event| is a manually resettable event and is signaled on 86 // WorkerThread::WakeUp() 87 virtual void WaitForWork(WaitableEvent* wake_up_event); 88 89 // Called by |worker|'s thread right before the main function exits. The 90 // Delegate is free to release any associated resources in this call. It is 91 // guaranteed that WorkerThread won't access the Delegate or the 92 // TaskTracker after calling OnMainExit() on the Delegate. OnMainExit(WorkerThread * worker)93 virtual void OnMainExit(WorkerThread* worker) {} 94 }; 95 96 // Creates a WorkerThread that runs Tasks from TaskSources returned by 97 // |delegate|. No actual thread will be created for this WorkerThread 98 // before Start() is called. |priority_hint| is the preferred thread priority; 99 // the actual thread priority depends on shutdown state and platform 100 // capabilities. |task_tracker| is used to handle shutdown behavior of Tasks. 101 // |predecessor_lock| is a lock that is allowed to be held when calling 102 // methods on this WorkerThread. |backward_compatibility| indicates 103 // whether backward compatibility is enabled. Either JoinForTesting() or 104 // Cleanup() must be called before releasing the last external reference. 105 WorkerThread(ThreadPriority priority_hint, 106 std::unique_ptr<Delegate> delegate, 107 TrackedRef<TaskTracker> task_tracker, 108 const CheckedLock* predecessor_lock = nullptr); 109 110 // Creates a thread to back the WorkerThread. The thread will be in a wait 111 // state pending a WakeUp() call. No thread will be created if Cleanup() was 112 // called. If specified, |worker_thread_observer| will be notified when the 113 // worker enters and exits its main function. It must not be destroyed before 114 // JoinForTesting() has returned (must never be destroyed in production). 115 // Returns true on success. 116 bool Start(WorkerThreadObserver* worker_thread_observer = nullptr); 117 118 // Wakes up this WorkerThread if it wasn't already awake. After this is 119 // called, this WorkerThread will run Tasks from TaskSources returned by 120 // the GetWork() method of its delegate until it returns nullptr. No-op if 121 // Start() wasn't called. DCHECKs if called after Start() has failed or after 122 // Cleanup() has been called. 123 void WakeUp(); 124 delegate()125 WorkerThread::Delegate* delegate() { return delegate_.get(); } 126 127 // Joins this WorkerThread. If a Task is already running, it will be 128 // allowed to complete its execution. This can only be called once. 129 // 130 // Note: A thread that detaches before JoinForTesting() is called may still be 131 // running after JoinForTesting() returns. However, it can't run tasks after 132 // JoinForTesting() returns. 133 void JoinForTesting(); 134 135 // Returns true if the worker is alive. 136 bool ThreadAliveForTesting() const; 137 138 // Makes a request to cleanup the worker. This may be called from any thread. 139 // The caller is expected to release its reference to this object after 140 // calling Cleanup(). Further method calls after Cleanup() returns are 141 // undefined. 142 // 143 // Expected Usage: 144 // scoped_refptr<WorkerThread> worker_ = /* Existing Worker */ 145 // worker_->Cleanup(); 146 // worker_ = nullptr; 147 void Cleanup(); 148 149 // Informs this WorkerThread about periods during which it is not being 150 // used. Thread-safe. 151 void BeginUnusedPeriod(); 152 void EndUnusedPeriod(); 153 // Returns the last time this WorkerThread was used. Returns a null time if 154 // this WorkerThread is currently in-use. Thread-safe. 155 TimeTicks GetLastUsedTime() const; 156 157 private: 158 friend class RefCountedThreadSafe<WorkerThread>; 159 class Thread; 160 161 ~WorkerThread() override; 162 163 bool ShouldExit() const; 164 165 // Returns the thread priority to use based on the priority hint, current 166 // shutdown state, and platform capabilities. 167 ThreadPriority GetDesiredThreadPriority() const; 168 169 // Changes the thread priority to |desired_thread_priority|. Must be called on 170 // the thread managed by |this|. 171 void UpdateThreadPriority(ThreadPriority desired_thread_priority); 172 173 // PlatformThread::Delegate: 174 void ThreadMain() override; 175 176 // Dummy frames to act as "RunLabeledWorker()" (see RunMain() below). Their 177 // impl is aliased to prevent compiler/linker from optimizing them out. 178 void RunPooledWorker(); 179 void RunBackgroundPooledWorker(); 180 void RunSharedWorker(); 181 void RunBackgroundSharedWorker(); 182 void RunDedicatedWorker(); 183 void RunBackgroundDedicatedWorker(); 184 #if defined(OS_WIN) 185 void RunSharedCOMWorker(); 186 void RunBackgroundSharedCOMWorker(); 187 void RunDedicatedCOMWorker(); 188 void RunBackgroundDedicatedCOMWorker(); 189 #endif // defined(OS_WIN) 190 191 // The real main, invoked through : 192 // ThreadMain() -> RunLabeledWorker() -> RunWorker(). 193 // "RunLabeledWorker()" is a dummy frame based on ThreadLabel+ThreadPriority 194 // and used to easily identify threads in stack traces. 195 void RunWorker(); 196 197 // Self-reference to prevent destruction of |this| while the thread is alive. 198 // Set in Start() before creating the thread. Reset in ThreadMain() before the 199 // thread exits. No lock required because the first access occurs before the 200 // thread is created and the second access occurs on the thread. 201 scoped_refptr<WorkerThread> self_; 202 203 mutable CheckedLock thread_lock_; 204 205 // Handle for the thread managed by |this|. 206 PlatformThreadHandle thread_handle_ GUARDED_BY(thread_lock_); 207 208 // The last time this worker was used by its owner (e.g. to process work or 209 // stand as a required idle thread). 210 TimeTicks last_used_time_ GUARDED_BY(thread_lock_); 211 212 // Event to wake up the thread managed by |this|. 213 WaitableEvent wake_up_event_{WaitableEvent::ResetPolicy::AUTOMATIC, 214 WaitableEvent::InitialState::NOT_SIGNALED}; 215 216 // Whether the thread should exit. Set by Cleanup(). 217 AtomicFlag should_exit_; 218 219 const std::unique_ptr<Delegate> delegate_; 220 const TrackedRef<TaskTracker> task_tracker_; 221 222 // Optional observer notified when a worker enters and exits its main 223 // function. Set in Start() and never modified afterwards. 224 WorkerThreadObserver* worker_thread_observer_ = nullptr; 225 226 // Desired thread priority. 227 const ThreadPriority priority_hint_; 228 229 // Actual thread priority. Can be different than |priority_hint_| depending on 230 // system capabilities and shutdown state. No lock required because all post- 231 // construction accesses occur on the thread. 232 ThreadPriority current_thread_priority_; 233 234 // Set once JoinForTesting() has been called. 235 AtomicFlag join_called_for_testing_; 236 237 DISALLOW_COPY_AND_ASSIGN(WorkerThread); 238 }; 239 240 } // namespace internal 241 } // namespace base 242 243 #endif // BASE_TASK_THREAD_POOL_WORKER_THREAD_H_ 244