1 // Copyright 2019 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_H_ 6 #define BASE_TASK_THREAD_POOL_H_ 7 8 #include <memory> 9 #include <utility> 10 11 #include "base/base_export.h" 12 #include "base/functional/bind.h" 13 #include "base/functional/callback.h" 14 #include "base/functional/callback_helpers.h" 15 #include "base/location.h" 16 #include "base/memory/scoped_refptr.h" 17 #include "base/task/post_task_and_reply_with_result_internal.h" 18 #include "base/task/sequenced_task_runner.h" 19 #include "base/task/single_thread_task_runner.h" 20 #include "base/task/single_thread_task_runner_thread_mode.h" 21 #include "base/task/task_runner.h" 22 #include "base/task/task_traits.h" 23 #include "base/task/updateable_sequenced_task_runner.h" 24 #include "base/time/time.h" 25 #include "build/build_config.h" 26 27 namespace base { 28 29 // This is the interface to post tasks to base's thread pool. 30 // 31 // To post a simple one-off task with default traits: 32 // base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(...)); 33 // 34 // To post a high priority one-off task to respond to a user interaction: 35 // base::ThreadPool::PostTask( 36 // FROM_HERE, 37 // {base::TaskPriority::USER_BLOCKING}, 38 // base::BindOnce(...)); 39 // 40 // To post tasks that must run in sequence with default traits: 41 // scoped_refptr<SequencedTaskRunner> task_runner = 42 // base::ThreadPool::CreateSequencedTaskRunner(); 43 // task_runner->PostTask(FROM_HERE, base::BindOnce(...)); 44 // task_runner->PostTask(FROM_HERE, base::BindOnce(...)); 45 // 46 // To post tasks that may block, must run in sequence and can be skipped on 47 // shutdown: 48 // scoped_refptr<SequencedTaskRunner> task_runner = 49 // base::ThreadPool::CreateSequencedTaskRunner( 50 // {MayBlock(), TaskShutdownBehavior::SKIP_ON_SHUTDOWN}); 51 // task_runner->PostTask(FROM_HERE, base::BindOnce(...)); 52 // task_runner->PostTask(FROM_HERE, base::BindOnce(...)); 53 // 54 // The default traits apply to tasks that: 55 // (1) don't block (ref. MayBlock() and WithBaseSyncPrimitives()), 56 // (2) prefer inheriting the current priority to specifying their own, and 57 // (3) can either block shutdown or be skipped on shutdown 58 // (implementation is free to choose a fitting default). 59 // Explicit traits must be specified for tasks for which these loose 60 // requirements are not sufficient. 61 // 62 // Prerequisite: A ThreadPoolInstance must have been registered for the current 63 // process via ThreadPoolInstance::Set() before the API below can be invoked. 64 // This is typically done during the initialization phase in each process. If 65 // your code is not running in that phase, you most likely don't have to worry 66 // about this. You will encounter DCHECKs or nullptr dereferences if this is 67 // violated. For tests, use base::test::TaskEnvironment. 68 class BASE_EXPORT ThreadPool { 69 public: 70 // base::ThreadPool is a static API. See base::ThreadPoolInstance for the 71 // actual instance. 72 ThreadPool() = delete; 73 74 // Equivalent to calling PostTask with default TaskTraits. 75 static bool PostTask(const Location& from_here, OnceClosure task); 76 inline static bool PostTask(OnceClosure task, 77 const Location& from_here = Location::Current()) { 78 return PostTask(from_here, std::move(task)); 79 } 80 81 // Equivalent to calling PostDelayedTask with default TaskTraits. 82 // 83 // Use PostDelayedTask to specify a BEST_EFFORT priority if the task doesn't 84 // have to run as soon as |delay| expires. 85 static bool PostDelayedTask(const Location& from_here, 86 OnceClosure task, 87 TimeDelta delay); 88 89 // Equivalent to calling PostTaskAndReply with default TaskTraits. 90 static bool PostTaskAndReply(const Location& from_here, 91 OnceClosure task, 92 OnceClosure reply); 93 94 // Equivalent to calling PostTaskAndReplyWithResult with default TaskTraits. 95 // 96 // Though RepeatingCallback is convertible to OnceCallback, we need a 97 // CallbackType template since we can not use template deduction and object 98 // conversion at once on the overload resolution. 99 // TODO(crbug.com/714018): Update all callers of the RepeatingCallback version 100 // to use OnceCallback and remove the CallbackType template. 101 template <template <typename> class CallbackType, 102 typename TaskReturnType, 103 typename ReplyArgType> requires(IsBaseCallback<CallbackType<void ()>>)104 requires(IsBaseCallback<CallbackType<void()>>) 105 static bool PostTaskAndReplyWithResult( 106 const Location& from_here, 107 CallbackType<TaskReturnType()> task, 108 CallbackType<void(ReplyArgType)> reply) { 109 return ThreadPool::PostTaskAndReplyWithResult( 110 from_here, {}, std::move(task), std::move(reply)); 111 } 112 113 // Posts |task| with specific |traits|. Returns false if the task definitely 114 // won't run because of current shutdown state. 115 static bool PostTask(const Location& from_here, 116 const TaskTraits& traits, 117 OnceClosure task); 118 119 // Posts |task| with specific |traits|. |task| will not run before |delay| 120 // expires. Returns false if the task definitely won't run because of current 121 // shutdown state. 122 // 123 // Specify a BEST_EFFORT priority via |traits| if the task doesn't have to run 124 // as soon as |delay| expires. 125 static bool PostDelayedTask(const Location& from_here, 126 const TaskTraits& traits, 127 OnceClosure task, 128 TimeDelta delay); 129 130 // Posts |task| with specific |traits| and posts |reply| on the caller's 131 // execution context (i.e. same sequence or thread and same TaskTraits if 132 // applicable) when |task| completes. Returns false if the task definitely 133 // won't run because of current shutdown state. Can only be called when 134 // SequencedTaskRunner::HasCurrentDefault(). 135 static bool PostTaskAndReply(const Location& from_here, 136 const TaskTraits& traits, 137 OnceClosure task, 138 OnceClosure reply); 139 140 // Posts |task| with specific |traits| and posts |reply| with the return value 141 // of |task| as argument on the caller's execution context (i.e. same sequence 142 // or thread and same TaskTraits if applicable) when |task| completes. Returns 143 // false if the task definitely won't run because of current shutdown state. 144 // Can only be called when SequencedTaskRunner::HasCurrentDefault(). 145 // 146 // Though RepeatingCallback is convertible to OnceCallback, we need a 147 // CallbackType template since we can not use template deduction and object 148 // conversion at once on the overload resolution. 149 // TODO(crbug.com/714018): Update all callers of the RepeatingCallback version 150 // to use OnceCallback and remove the CallbackType template. 151 template <template <typename> class CallbackType, 152 typename TaskReturnType, 153 typename ReplyArgType> requires(IsBaseCallback<CallbackType<void ()>>)154 requires(IsBaseCallback<CallbackType<void()>>) 155 static bool PostTaskAndReplyWithResult( 156 const Location& from_here, 157 const TaskTraits& traits, 158 CallbackType<TaskReturnType()> task, 159 CallbackType<void(ReplyArgType)> reply) { 160 auto* result = new std::unique_ptr<TaskReturnType>(); 161 return PostTaskAndReply( 162 from_here, traits, 163 BindOnce(&internal::ReturnAsParamAdapter<TaskReturnType>, 164 std::move(task), result), 165 BindOnce(&internal::ReplyAdapter<TaskReturnType, ReplyArgType>, 166 std::move(reply), Owned(result))); 167 } 168 169 // Returns a TaskRunner whose PostTask invocations result in scheduling tasks 170 // using |traits|. Tasks may run in any order and in parallel. 171 static scoped_refptr<TaskRunner> CreateTaskRunner(const TaskTraits& traits); 172 173 // Returns a SequencedTaskRunner whose PostTask invocations result in 174 // scheduling tasks using |traits|. Tasks run one at a time in posting order. 175 static scoped_refptr<SequencedTaskRunner> CreateSequencedTaskRunner( 176 const TaskTraits& traits); 177 178 // Returns a task runner whose PostTask invocations result in scheduling tasks 179 // using |traits|. The priority in |traits| can be updated at any time via 180 // UpdateableSequencedTaskRunner::UpdatePriority(). An update affects all 181 // tasks posted to the task runner that aren't running yet. Tasks run one at a 182 // time in posting order. 183 // 184 // |traits| requirements: 185 // - base::ThreadPolicy must be specified if the priority of the task runner 186 // will ever be increased from BEST_EFFORT. 187 static scoped_refptr<UpdateableSequencedTaskRunner> 188 CreateUpdateableSequencedTaskRunner(const TaskTraits& traits); 189 190 // Returns a SingleThreadTaskRunner whose PostTask invocations result in 191 // scheduling tasks using |traits| on a thread determined by |thread_mode|. 192 // See base/task/single_thread_task_runner_thread_mode.h for |thread_mode| 193 // details. If |traits| identifies an existing thread, 194 // SingleThreadTaskRunnerThreadMode::SHARED must be used. Tasks run on a 195 // single thread in posting order. 196 // 197 // If all you need is to make sure that tasks don't run concurrently (e.g. 198 // because they access a data structure which is not thread-safe), use 199 // CreateSequencedTaskRunner(). Only use this if you rely on a thread-affine 200 // API (it might be safer to assume thread-affinity when dealing with 201 // under-documented third-party APIs, e.g. other OS') or share data across 202 // tasks using thread-local storage. 203 static scoped_refptr<SingleThreadTaskRunner> CreateSingleThreadTaskRunner( 204 const TaskTraits& traits, 205 SingleThreadTaskRunnerThreadMode thread_mode = 206 SingleThreadTaskRunnerThreadMode::SHARED); 207 208 #if BUILDFLAG(IS_WIN) 209 // Returns a SingleThreadTaskRunner whose PostTask invocations result in 210 // scheduling tasks using |traits| in a COM Single-Threaded Apartment on a 211 // thread determined by |thread_mode|. See 212 // base/task/single_thread_task_runner_thread_mode.h for |thread_mode| 213 // details. If |traits| identifies an existing thread, 214 // SingleThreadTaskRunnerThreadMode::SHARED must be used. Tasks run in the 215 // same Single-Threaded Apartment in posting order for the returned 216 // SingleThreadTaskRunner. There is not necessarily a one-to-one 217 // correspondence between SingleThreadTaskRunners and Single-Threaded 218 // Apartments. The implementation is free to share apartments or create new 219 // apartments as necessary. In either case, care should be taken to make sure 220 // COM pointers are not smuggled across apartments. 221 static scoped_refptr<SingleThreadTaskRunner> CreateCOMSTATaskRunner( 222 const TaskTraits& traits, 223 SingleThreadTaskRunnerThreadMode thread_mode = 224 SingleThreadTaskRunnerThreadMode::SHARED); 225 #endif // BUILDFLAG(IS_WIN) 226 }; 227 228 } // namespace base 229 230 #endif // BASE_TASK_THREAD_POOL_H_ 231