xref: /aosp_15_r20/external/cronet/base/task/thread_pool/thread_group_worker_delegate.h (revision 6777b5387eb2ff775bb5750e3f5d96f37fb7352b)
1 // Copyright 2023 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 #ifndef BASE_TASK_THREAD_POOL_THREAD_GROUP_WORKER_DELEGATE_H_
6 #define BASE_TASK_THREAD_POOL_THREAD_GROUP_WORKER_DELEGATE_H_
7 
8 #include <optional>
9 
10 #include "base/metrics/histogram_macros.h"
11 #include "base/task/task_traits.h"
12 #include "base/task/thread_pool/thread_group.h"
13 #include "base/task/thread_pool/worker_thread.h"
14 #include "base/threading/scoped_blocking_call.h"
15 #include "base/threading/scoped_blocking_call_internal.h"
16 #include "base/threading/thread_checker.h"
17 
18 namespace base::internal {
19 
20 // This class is not a WorkerThread::Delegate, instead implementing
21 // functionality which is common to all WorkerThread::Delegates present in a
22 // ThreadGroup.
23 class ThreadGroup::ThreadGroupWorkerDelegate : public BlockingObserver {
24  public:
25   explicit ThreadGroupWorkerDelegate(TrackedRef<ThreadGroup> outer,
26                                      bool is_excess);
27   ThreadGroupWorkerDelegate(const ThreadGroupWorkerDelegate&) = delete;
28   ThreadGroupWorkerDelegate& operator=(const ThreadGroupWorkerDelegate&) =
29       delete;
30 
31   ~ThreadGroupWorkerDelegate() override;
32 
33   TimeDelta ThreadPoolSleepTimeout();
34 
35   // BlockingObserver:
36   void BlockingStarted(BlockingType blocking_type) override;
37   void BlockingTypeUpgraded() override;
38   void BlockingEnded() override;
39 
40   // Notifies the worker of shutdown, possibly marking the running task as
41   // MAY_BLOCK.
42   void OnShutdownStartedLockRequired(BaseScopedCommandsExecutor* executor)
43       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
44 
45   // Increments max [best effort] tasks iff this worker has been within a
46   // ScopedBlockingCall for more than |may_block_threshold|.
47   void MaybeIncrementMaxTasksLockRequired()
48       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
49 
50   // Increments max [best effort] tasks.
51   void IncrementMaxTasksLockRequired() EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
52 
current_task_priority_lock_required()53   TaskPriority current_task_priority_lock_required() const
54       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) {
55     return *read_any().current_task_priority;
56   }
57 
58   // Exposed for AnnotateAcquiredLockAlias.
lock()59   const CheckedLock& lock() const LOCK_RETURNED(outer_->lock_) {
60     return outer_->lock_;
61   }
62 
63  protected:
64   // Returns true if |worker| is allowed to cleanup and remove itself from the
65   // thread group. Called from GetWork() when no work is available.
66   virtual bool CanCleanupLockRequired(const WorkerThread* worker)
67       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) = 0;
68 
69   // Returns true iff the worker can get work. Cleans up the worker or puts it
70   // on the idle set if it can't get work.
71   virtual bool CanGetWorkLockRequired(BaseScopedCommandsExecutor* executor,
72                                       WorkerThread* worker)
73       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) = 0;
74 
75   RegisteredTaskSource GetWorkLockRequired(BaseScopedCommandsExecutor* executor,
76                                            WorkerThread* worker)
77       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_);
78 
79   // Calls cleanup on |worker| and removes it from the thread group. Called from
80   // GetWork() when no work is available and CanCleanupLockRequired() returns
81   // true.
82   virtual void CleanupLockRequired(BaseScopedCommandsExecutor* executor,
83                                    WorkerThread* worker)
84       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) = 0;
85 
86   // Called in GetWork() when a worker becomes idle.
87   virtual void OnWorkerBecomesIdleLockRequired(
88       BaseScopedCommandsExecutor* executor,
89       WorkerThread* worker) EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) = 0;
90 
91   // See worker_thread.h for documentation.
92   void OnMainEntryImpl(WorkerThread* worker);
93   void RecordUnnecessaryWakeupImpl();
94 
95   // Only used in DCHECKs.
96   template <typename Worker>
ContainsWorker(const std::vector<scoped_refptr<Worker>> & workers,const WorkerThread * worker)97   bool ContainsWorker(const std::vector<scoped_refptr<Worker>>& workers,
98                       const WorkerThread* worker) {
99     auto it = ranges::find_if(
100         workers,
101         [worker](const scoped_refptr<Worker>& i) { return i.get() == worker; });
102     return it != workers.end();
103   }
104 
105   // Accessed only from the worker thread.
106   struct WorkerOnly {
107     WorkerOnly();
108     ~WorkerOnly();
109     // Associated WorkerThread, if any, initialized in OnMainEntry().
110     raw_ptr<WorkerThread> worker_thread_;
111 
112 #if BUILDFLAG(IS_WIN)
113     std::unique_ptr<win::ScopedWindowsThreadEnvironment> win_thread_environment;
114 #endif  // BUILDFLAG(IS_WIN)
115   } worker_only_;
116 
117   // Writes from the worker thread protected by |outer_->lock_|. Reads from any
118   // thread, protected by |outer_->lock_| when not on the worker thread.
119   struct WriteWorkerReadAny {
120     // The priority of the task the worker is currently running if any.
121     std::optional<TaskPriority> current_task_priority;
122     // The shutdown behavior of the task the worker is currently running if any.
123     std::optional<TaskShutdownBehavior> current_shutdown_behavior;
124 
125     // Time when MayBlockScopeEntered() was last called. Reset when
126     // BlockingScopeExited() is called.
127     TimeTicks blocking_start_time;
128 
129     // Whether the worker is currently running a task (i.e. GetWork() has
130     // returned a non-empty task source and DidProcessTask() hasn't been called
131     // yet).
is_running_taskWriteWorkerReadAny132     bool is_running_task() const { return !!current_shutdown_behavior; }
133   } write_worker_read_any_;
134 
worker_only()135   WorkerOnly& worker_only() {
136     DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
137     return worker_only_;
138   }
139 
write_worker()140   WriteWorkerReadAny& write_worker() EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) {
141     DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
142     return write_worker_read_any_;
143   }
144 
read_any()145   const WriteWorkerReadAny& read_any() const
146       EXCLUSIVE_LOCKS_REQUIRED(outer_->lock_) {
147     return write_worker_read_any_;
148   }
149 
read_worker()150   const WriteWorkerReadAny& read_worker() const {
151     DCHECK_CALLED_ON_VALID_THREAD(worker_thread_checker_);
152     return write_worker_read_any_;
153   }
154 
155   const TrackedRef<ThreadGroup> outer_;
156 
157   // Whether the worker is in excess. This must be decided at worker creation
158   // time to prevent unnecessarily discarding TLS state, as well as any behavior
159   // the OS has learned about a given thread.
160   const bool is_excess_;
161 
162   // Whether |outer_->max_tasks_|/|outer_->max_best_effort_tasks_| were
163   // incremented due to a ScopedBlockingCall on the thread.
164   bool incremented_max_tasks_since_blocked_ GUARDED_BY(outer_->lock_) = false;
165   bool incremented_max_best_effort_tasks_since_blocked_
166       GUARDED_BY(outer_->lock_) = false;
167   // Whether |outer_->max_tasks_| and |outer_->max_best_effort_tasks_| was
168   // incremented due to running CONTINUE_ON_SHUTDOWN on the thread during
169   // shutdown.
170   bool incremented_max_tasks_for_shutdown_ GUARDED_BY(outer_->lock_) = false;
171 
172   // Verifies that specific calls are always made from the worker thread.
173   THREAD_CHECKER(worker_thread_checker_);
174 };
175 
176 }  // namespace base::internal
177 
178 #endif  // BASE_TASK_THREAD_POOL_THREAD_GROUP_WORKER_DELEGATE_H_
179