1 // Copyright 2017 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_POOLED_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_ 6 #define BASE_TASK_THREAD_POOL_POOLED_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_ 7 8 #include <memory> 9 #include <string> 10 #include <vector> 11 12 #include "base/base_export.h" 13 #include "base/memory/raw_ptr.h" 14 #include "base/task/common/checked_lock.h" 15 #include "base/task/single_thread_task_runner_thread_mode.h" 16 #include "base/task/thread_pool/environment_config.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 "build/build_config.h" 21 22 namespace base { 23 24 class TaskTraits; 25 class WorkerThreadObserver; 26 class SingleThreadTaskRunner; 27 28 namespace internal { 29 30 class DelayedTaskManager; 31 class WorkerThreadWaitableEvent; 32 class TaskTracker; 33 34 namespace { 35 36 class WorkerThreadDelegate; 37 38 } // namespace 39 40 // Manages a group of threads which are each associated with one or more 41 // SingleThreadTaskRunners. 42 // 43 // SingleThreadTaskRunners using SingleThreadTaskRunnerThreadMode::SHARED are 44 // backed by shared WorkerThreads for each COM+task environment combination. 45 // These workers are lazily instantiated and then only reclaimed during 46 // JoinForTesting() 47 // 48 // No threads are created (and hence no tasks can run) before Start() is called. 49 // 50 // This class is thread-safe. 51 class BASE_EXPORT PooledSingleThreadTaskRunnerManager final { 52 public: 53 PooledSingleThreadTaskRunnerManager(TrackedRef<TaskTracker> task_tracker, 54 DelayedTaskManager* delayed_task_manager); 55 PooledSingleThreadTaskRunnerManager( 56 const PooledSingleThreadTaskRunnerManager&) = delete; 57 PooledSingleThreadTaskRunnerManager& operator=( 58 const PooledSingleThreadTaskRunnerManager&) = delete; 59 ~PooledSingleThreadTaskRunnerManager(); 60 61 // Starts threads for existing SingleThreadTaskRunners and allows threads to 62 // be started when SingleThreadTaskRunners are created in the future. 63 // `io_thread_task_runner` is used to setup FileDescriptorWatcher on worker 64 // threads. `io_thread_task_runner` must refer to a Thread with 65 // MessgaePumpType::IO. If specified, |worker_thread_observer| will be 66 // notified when a worker enters and exits its main function. It must not be 67 // destroyed before JoinForTesting() has returned (must never be destroyed in 68 // production). 69 void Start(scoped_refptr<SingleThreadTaskRunner> io_thread_task_runner, 70 WorkerThreadObserver* worker_thread_observer = nullptr); 71 72 // Wakes up workers as appropriate for the new CanRunPolicy policy. Must be 73 // called after an update to CanRunPolicy in TaskTracker. 74 void DidUpdateCanRunPolicy(); 75 76 // Creates a SingleThreadTaskRunner which runs tasks with |traits| on a thread 77 // named "ThreadPoolSingleThread[Shared]" + 78 // kEnvironmentParams[GetEnvironmentIndexForTraits(traits)].name_suffix + 79 // index. 80 scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunner( 81 const TaskTraits& traits, 82 SingleThreadTaskRunnerThreadMode thread_mode); 83 84 #if BUILDFLAG(IS_WIN) 85 // Creates a SingleThreadTaskRunner which runs tasks with |traits| on a COM 86 // STA thread named "ThreadPoolSingleThreadCOMSTA[Shared]" + 87 // kEnvironmentParams[GetEnvironmentIndexForTraits(traits)].name_suffix + 88 // index. 89 scoped_refptr<SingleThreadTaskRunner> CreateCOMSTATaskRunner( 90 const TaskTraits& traits, 91 SingleThreadTaskRunnerThreadMode thread_mode); 92 #endif // BUILDFLAG(IS_WIN) 93 94 void JoinForTesting(); 95 96 private: 97 class PooledSingleThreadTaskRunner; 98 99 enum ContinueOnShutdown { 100 IS_CONTINUE_ON_SHUTDOWN, 101 IS_NOT_CONTINUE_ON_SHUTDOWN, 102 CONTINUE_ON_SHUTDOWN_COUNT, 103 }; 104 105 static ContinueOnShutdown TraitsToContinueOnShutdown( 106 const TaskTraits& traits); 107 108 template <typename DelegateType> 109 scoped_refptr<PooledSingleThreadTaskRunner> CreateTaskRunnerImpl( 110 const TaskTraits& traits, 111 SingleThreadTaskRunnerThreadMode thread_mode); 112 113 template <typename DelegateType> 114 std::unique_ptr<WorkerThreadDelegate> CreateWorkerThreadDelegate( 115 const std::string& name, 116 int id, 117 SingleThreadTaskRunnerThreadMode thread_mode); 118 119 template <typename DelegateType> 120 WorkerThreadWaitableEvent* CreateAndRegisterWorkerThread( 121 const std::string& name, 122 SingleThreadTaskRunnerThreadMode thread_mode, 123 ThreadType thread_type_hint) EXCLUSIVE_LOCKS_REQUIRED(lock_); 124 125 template <typename DelegateType> 126 WorkerThreadWaitableEvent*& GetSharedWorkerThreadForTraits( 127 const TaskTraits& traits); 128 129 void UnregisterWorkerThread(WorkerThreadWaitableEvent* worker); 130 131 void ReleaseSharedWorkerThreads(); 132 133 const TrackedRef<TaskTracker> task_tracker_; 134 const raw_ptr<DelayedTaskManager> delayed_task_manager_; 135 136 scoped_refptr<SingleThreadTaskRunner> io_thread_task_runner_; 137 138 // Optional observer notified when a worker enters and exits its main 139 // function. Set in Start() and never modified afterwards. 140 raw_ptr<WorkerThreadObserver> worker_thread_observer_ = nullptr; 141 142 CheckedLock lock_; 143 std::vector<scoped_refptr<WorkerThreadWaitableEvent>> workers_ 144 GUARDED_BY(lock_); 145 int next_worker_id_ GUARDED_BY(lock_) = 0; 146 147 // Workers for SingleThreadTaskRunnerThreadMode::SHARED tasks. It is 148 // important to have separate threads for CONTINUE_ON_SHUTDOWN and non- 149 // CONTINUE_ON_SHUTDOWN to avoid being in a situation where a 150 // CONTINUE_ON_SHUTDOWN task effectively blocks shutdown by preventing a 151 // BLOCK_SHUTDOWN task to be scheduled. https://crbug.com/829786 152 WorkerThreadWaitableEvent* 153 shared_worker_threads_[ENVIRONMENT_COUNT] 154 [CONTINUE_ON_SHUTDOWN_COUNT] GUARDED_BY(lock_) = {}; 155 #if BUILDFLAG(IS_WIN) 156 WorkerThreadWaitableEvent* shared_com_worker_threads_ 157 [ENVIRONMENT_COUNT][CONTINUE_ON_SHUTDOWN_COUNT] GUARDED_BY(lock_) = {}; 158 #endif // BUILDFLAG(IS_WIN) 159 160 // Set to true when Start() is called. 161 bool started_ GUARDED_BY(lock_) = false; 162 }; 163 164 } // namespace internal 165 } // namespace base 166 167 #endif // BASE_TASK_THREAD_POOL_POOLED_SINGLE_THREAD_TASK_RUNNER_MANAGER_H_ 168