blob: ebe88fbc0d82a002a06a442990e520c49c90eb45 [file] [log] [blame] [view]
fdoraybacba4a22017-05-10 21:10:001# Threading and Tasks in Chrome
2
3[TOC]
4
Gabriel Charette8917f4c2018-11-22 15:50:285Note: See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more
6examples.
7
fdoraybacba4a22017-05-10 21:10:008## Overview
9
Gabriel Charette39db4c62019-04-29 19:52:3810Chrome has a [multi-process
11architecture](https://www.chromium.org/developers/design-documents/multi-process-architecture)
12and each process is heavily multi-threaded. In this document we will go over the
13basic threading system shared by each process. The main goal is to keep the main
14thread (a.k.a. "UI" thread in the browser process) and IO thread (each process'
15thread for handling
16[IPC](https://en.wikipedia.org/wiki/Inter-process_communication)) responsive.
17This means offloading any blocking I/O or other expensive operations to other
18threads. Our approach is to use message passing as the way of communicating
19between threads. We discourage locking and thread-safe objects. Instead, objects
20live on only one (often virtual -- we'll get to that later!) thread and we pass
Albert J. Wongf06ff5002021-07-08 20:37:0021messages between those threads for communication. Absent external requirements
22about latency or workload, Chrome attempts to be a [highly concurrent, but not
Jared Saulea867ab2021-07-15 17:39:0123necessarily parallel](https://stackoverflow.com/questions/1050222/what-is-the-difference-between-concurrency-and-parallelism#:~:text=Concurrency%20is%20when%20two%20or,e.g.%2C%20on%20a%20multicore%20processor.),
24system.
Gabriel Charette39db4c62019-04-29 19:52:3825
26This documentation assumes familiarity with computer science
27[threading concepts](https://en.wikipedia.org/wiki/Thread_(computing)).
Gabriel Charette90480312018-02-16 15:10:0528
Gabriel Charette364a16a2019-02-06 21:12:1529### Nomenclature
Gabriel Charette39db4c62019-04-29 19:52:3830
31## Core Concepts
32 * **Task**: A unit of work to be processed. Effectively a function pointer with
Alex St-Onge490a97a2021-02-04 02:47:1933 optionally associated state. In Chrome this is `base::OnceCallback` and
34 `base::RepeatingCallback` created via `base::BindOnce` and
35 `base::BindRepeating`, respectively.
Gabriel Charette39db4c62019-04-29 19:52:3836 ([documentation](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/callback.md)).
37 * **Task queue**: A queue of tasks to be processed.
38 * **Physical thread**: An operating system provided thread (e.g. pthread on
39 POSIX or CreateThread() on Windows). The Chrome cross-platform abstraction
40 is `base::PlatformThread`. You should pretty much never use this directly.
41 * **`base::Thread`**: A physical thread forever processing messages from a
42 dedicated task queue until Quit(). You should pretty much never be creating
43 your own `base::Thread`'s.
44 * **Thread pool**: A pool of physical threads with a shared task queue. In
Gabriel Charette0b20ee6c2019-09-18 14:06:1245 Chrome, this is `base::ThreadPoolInstance`. There's exactly one instance per
46 Chrome process, it serves tasks posted through
Gabriel Charette39db4c62019-04-29 19:52:3847 [`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h)
Gabriel Charette43fd3702019-05-29 16:36:5148 and as such you should rarely need to use the `base::ThreadPoolInstance` API
Gabriel Charette39db4c62019-04-29 19:52:3849 directly (more on posting tasks later).
50 * **Sequence** or **Virtual thread**: A chrome-managed thread of execution.
51 Like a physical thread, only one task can run on a given sequence / virtual
52 thread at any given moment and each task sees the side-effects of the
53 preceding tasks. Tasks are executed sequentially but may hop physical
54 threads between each one.
55 * **Task runner**: An interface through which tasks can be posted. In Chrome
56 this is `base::TaskRunner`.
57 * **Sequenced task runner**: A task runner which guarantees that tasks posted
58 to it will run sequentially, in posted order. Each such task is guaranteed to
59 see the side-effects of the task preceding it. Tasks posted to a sequenced
60 task runner are typically processed by a single thread (virtual or physical).
61 In Chrome this is `base::SequencedTaskRunner` which is-a
62 `base::TaskRunner`.
63 * **Single-thread task runner**: A sequenced task runner which guarantees that
64 all tasks will be processed by the same physical thread. In Chrome this is
65 `base::SingleThreadTaskRunner` which is-a `base::SequencedTaskRunner`. We
66 [prefer sequences to threads](#prefer-sequences-to-physical-threads) whenever
67 possible.
68
69## Threading Lexicon
70Note to the reader: the following terms are an attempt to bridge the gap between
71common threading nomenclature and the way we use them in Chrome. It might be a
72bit heavy if you're just getting started. Should this be hard to parse, consider
73skipping to the more detailed sections below and referring back to this as
74necessary.
75
76 * **Thread-unsafe**: The vast majority of types in Chrome are thread-unsafe
77 (by design). Access to such types/methods must be externally synchronized.
78 Typically thread-unsafe types require that all tasks accessing their state be
79 posted to the same `base::SequencedTaskRunner` and they verify this in debug
80 builds with a `SEQUENCE_CHECKER` member. Locks are also an option to
81 synchronize access but in Chrome we strongly
82 [prefer sequences to locks](#Using-Sequences-Instead-of-Locks).
Gabriel Charette364a16a2019-02-06 21:12:1583 * **Thread-affine**: Such types/methods need to be always accessed from the
Gabriel Charetteb984d672019-02-12 21:53:2784 same physical thread (i.e. from the same `base::SingleThreadTaskRunner`) and
Gabriel Charette39db4c62019-04-29 19:52:3885 typically have a `THREAD_CHECKER` member to verify that they are. Short of
86 using a third-party API or having a leaf dependency which is thread-affine:
87 there's pretty much no reason for a type to be thread-affine in Chrome.
88 Note that `base::SingleThreadTaskRunner` is-a `base::SequencedTaskRunner` so
Gabriel Charetteb984d672019-02-12 21:53:2789 thread-affine is a subset of thread-unsafe. Thread-affine is also sometimes
90 referred to as **thread-hostile**.
Albert J. Wongf06ff5002021-07-08 20:37:0091 * **Thread-safe**: Such types/methods can be safely accessed in parallel.
92 * **Thread-compatible**: Such types provide safe parallel access to const
Gabriel Charetteb984d672019-02-12 21:53:2793 methods but require synchronization for non-const (or mixed const/non-const
Gabriel Charette39db4c62019-04-29 19:52:3894 access). Chrome doesn't expose reader-writer locks; as such, the only use
Gabriel Charetteb984d672019-02-12 21:53:2795 case for this is objects (typically globals) which are initialized once in a
Gabriel Charette364a16a2019-02-06 21:12:1596 thread-safe manner (either in the single-threaded phase of startup or lazily
97 through a thread-safe static-local-initialization paradigm a la
Gabriel Charetteb984d672019-02-12 21:53:2798 `base::NoDestructor`) and forever after immutable.
99 * **Immutable**: A subset of thread-compatible types which cannot be modified
100 after construction.
Gabriel Charette364a16a2019-02-06 21:12:15101 * **Sequence-friendly**: Such types/methods are thread-unsafe types which
102 support being invoked from a `base::SequencedTaskRunner`. Ideally this would
103 be the case for all thread-unsafe types but legacy code sometimes has
104 overzealous checks that enforce thread-affinity in mere thread-unsafe
Gabriel Charette39db4c62019-04-29 19:52:38105 scenarios. See [Prefer Sequences to
106 Threads](#prefer-sequences-to-physical-threads) below for more details.
Gabriel Charette364a16a2019-02-06 21:12:15107
fdoraybacba4a22017-05-10 21:10:00108### Threads
109
110Every Chrome process has
111
112* a main thread
Gabriel Charette39db4c62019-04-29 19:52:38113 * in the browser process (BrowserThread::UI): updates the UI
114 * in renderer processes (Blink main thread): runs most of Blink
fdoraybacba4a22017-05-10 21:10:00115* an IO thread
Gabriel Charette49e3cd02020-01-28 03:45:27116 * in the browser process (BrowserThread::IO): handles IPCs and network
117 requests
fdoraybacba4a22017-05-10 21:10:00118 * in renderer processes: handles IPCs
119* a few more special-purpose threads
120* and a pool of general-purpose threads
121
122Most threads have a loop that gets tasks from a queue and runs them (the queue
123may be shared between multiple threads).
124
125### Tasks
126
127A task is a `base::OnceClosure` added to a queue for asynchronous execution.
128
129A `base::OnceClosure` stores a function pointer and arguments. It has a `Run()`
130method that invokes the function pointer using the bound arguments. It is
131created using `base::BindOnce`. (ref. [Callback<> and Bind()
132documentation](callback.md)).
133
134```
135void TaskA() {}
136void TaskB(int v) {}
137
138auto task_a = base::BindOnce(&TaskA);
139auto task_b = base::BindOnce(&TaskB, 42);
140```
141
142A group of tasks can be executed in one of the following ways:
143
144* [Parallel](#Posting-a-Parallel-Task): No task execution ordering, possibly all
145 at once on any thread
146* [Sequenced](#Posting-a-Sequenced-Task): Tasks executed in posting order, one
147 at a time on any thread.
148* [Single Threaded](#Posting-Multiple-Tasks-to-the-Same-Thread): Tasks executed
149 in posting order, one at a time on a single thread.
Drew Stonebraker653a3ba2019-07-02 19:24:23150 * [COM Single Threaded](#Posting-Tasks-to-a-COM-Single_Thread-Apartment-STA_Thread-Windows):
fdoraybacba4a22017-05-10 21:10:00151 A variant of single threaded with COM initialized.
152
Gabriel Charette39db4c62019-04-29 19:52:38153### Prefer Sequences to Physical Threads
gab2a4576052017-06-07 23:36:12154
Gabriel Charette39db4c62019-04-29 19:52:38155Sequenced execution (on virtual threads) is strongly preferred to
156single-threaded execution (on physical threads). Except for types/methods bound
157to the main thread (UI) or IO threads: thread-safety is better achieved via
158`base::SequencedTaskRunner` than through managing your own physical threads
159(ref. [Posting a Sequenced Task](#posting-a-sequenced-task) below).
gab2a4576052017-06-07 23:36:12160
Gabriel Charette39db4c62019-04-29 19:52:38161All APIs which are exposed for "current physical thread" have an equivalent for
162"current sequence"
163([mapping](threading_and_tasks_faq.md#How-to-migrate-from-SingleThreadTaskRunner-to-SequencedTaskRunner)).
gab2a4576052017-06-07 23:36:12164
Gabriel Charette39db4c62019-04-29 19:52:38165If you find yourself writing a sequence-friendly type and it fails
166thread-affinity checks (e.g., `THREAD_CHECKER`) in a leaf dependency: consider
167making that dependency sequence-friendly as well. Most core APIs in Chrome are
168sequence-friendly, but some legacy types may still over-zealously use
169ThreadChecker/ThreadTaskRunnerHandle/SingleThreadTaskRunner when they could
170instead rely on the "current sequence" and no longer be thread-affine.
fdoraybacba4a22017-05-10 21:10:00171
172## Posting a Parallel Task
173
Gabriel Charette52fa3ae2019-04-15 21:44:37174### Direct Posting to the Thread Pool
fdoraybacba4a22017-05-10 21:10:00175
176A task that can run on any thread and doesn’t have ordering or mutual exclusion
177requirements with other tasks should be posted using one of the
Gabriel Charette43de5c42020-01-27 22:44:45178`base::ThreadPool::PostTask*()` functions defined in
179[`base/task/thread_pool.h`](https://cs.chromium.org/chromium/src/base/task/thread_pool.h).
fdoraybacba4a22017-05-10 21:10:00180
181```cpp
Gabriel Charette43de5c42020-01-27 22:44:45182base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(&Task));
fdoraybacba4a22017-05-10 21:10:00183```
184
185This posts tasks with default traits.
186
Gabriel Charette43de5c42020-01-27 22:44:45187The `base::ThreadPool::PostTask*()` functions allow the caller to provide
188additional details about the task via TaskTraits (ref. [Annotating Tasks with
189TaskTraits](#Annotating-Tasks-with-TaskTraits)).
fdoraybacba4a22017-05-10 21:10:00190
191```cpp
Gabriel Charette43de5c42020-01-27 22:44:45192base::ThreadPool::PostTask(
Gabriel Charetteb10aeebc2018-07-26 20:15:00193 FROM_HERE, {base::TaskPriority::BEST_EFFORT, MayBlock()},
fdoraybacba4a22017-05-10 21:10:00194 base::BindOnce(&Task));
195```
196
fdoray52bf5552017-05-11 12:43:59197### Posting via a TaskRunner
fdoraybacba4a22017-05-10 21:10:00198
199A parallel
Gabriel Charette39db4c62019-04-29 19:52:38200[`base::TaskRunner`](https://cs.chromium.org/chromium/src/base/task_runner.h) is
Gabriel Charette43de5c42020-01-27 22:44:45201an alternative to calling `base::ThreadPool::PostTask*()` directly. This is
202mainly useful when it isn’t known in advance whether tasks will be posted in
203parallel, in sequence, or to a single-thread (ref. [Posting a Sequenced
Gabriel Charette39db4c62019-04-29 19:52:38204Task](#Posting-a-Sequenced-Task), [Posting Multiple Tasks to the Same
205Thread](#Posting-Multiple-Tasks-to-the-Same-Thread)). Since `base::TaskRunner`
206is the base class of `base::SequencedTaskRunner` and
207`base::SingleThreadTaskRunner`, a `scoped_refptr<TaskRunner>` member can hold a
208`base::TaskRunner`, a `base::SequencedTaskRunner` or a
209`base::SingleThreadTaskRunner`.
fdoraybacba4a22017-05-10 21:10:00210
211```cpp
212class A {
213 public:
214 A() = default;
215
Gabriel Charette43de5c42020-01-27 22:44:45216 void PostSomething() {
217 task_runner_->PostTask(FROM_HERE, base::BindOnce(&A, &DoSomething));
218 }
219
fdoraybacba4a22017-05-10 21:10:00220 void DoSomething() {
fdoraybacba4a22017-05-10 21:10:00221 }
222
223 private:
224 scoped_refptr<base::TaskRunner> task_runner_ =
Gabriel Charette43de5c42020-01-27 22:44:45225 base::ThreadPool::CreateTaskRunner({base::TaskPriority::USER_VISIBLE});
fdoraybacba4a22017-05-10 21:10:00226};
227```
228
229Unless a test needs to control precisely how tasks are executed, it is preferred
Gabriel Charette49e3cd02020-01-28 03:45:27230to call `base::ThreadPool::PostTask*()` directly (ref. [Testing](#Testing) for
231less invasive ways of controlling tasks in tests).
fdoraybacba4a22017-05-10 21:10:00232
233## Posting a Sequenced Task
234
235A sequence is a set of tasks that run one at a time in posting order (not
236necessarily on the same thread). To post tasks as part of a sequence, use a
Gabriel Charette39db4c62019-04-29 19:52:38237[`base::SequencedTaskRunner`](https://cs.chromium.org/chromium/src/base/sequenced_task_runner.h).
fdoraybacba4a22017-05-10 21:10:00238
239### Posting to a New Sequence
240
Gabriel Charette39db4c62019-04-29 19:52:38241A `base::SequencedTaskRunner` can be created by
Gabriel Charette43de5c42020-01-27 22:44:45242`base::ThreadPool::CreateSequencedTaskRunner()`.
fdoraybacba4a22017-05-10 21:10:00243
244```cpp
245scoped_refptr<SequencedTaskRunner> sequenced_task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45246 base::ThreadPool::CreateSequencedTaskRunner(...);
fdoraybacba4a22017-05-10 21:10:00247
248// TaskB runs after TaskA completes.
249sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
250sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
251```
252
Alex Clarke0dd499562019-10-18 19:45:09253### Posting to the Current (Virtual) Thread
254
Gabriel Charettefee55662019-11-20 21:06:28255The preferred way of posting to the current (virtual) thread is via
256`base::SequencedTaskRunnerHandle::Get()`.
Alex Clarke0dd499562019-10-18 19:45:09257
258```cpp
259// The task will run on the current (virtual) thread's default task queue.
Gabriel Charettefee55662019-11-20 21:06:28260base::SequencedTaskRunnerHandle::Get()->PostTask(
261 FROM_HERE, base::BindOnce(&Task);
Alex Clarke0dd499562019-10-18 19:45:09262```
263
Jared Saulea867ab2021-07-15 17:39:01264Note that `SequencedTaskRunnerHandle::Get()` returns the default queue for the
Gabriel Charettefee55662019-11-20 21:06:28265current virtual thread. On threads with multiple task queues (e.g.
266BrowserThread::UI) this can be a different queue than the one the current task
267belongs to. The "current" task runner is intentionally not exposed via a static
268getter. Either you know it already and can post to it directly or you don't and
269the only sensible destination is the default queue.
Alex Clarke0dd499562019-10-18 19:45:09270
fdoraybacba4a22017-05-10 21:10:00271## Using Sequences Instead of Locks
272
273Usage of locks is discouraged in Chrome. Sequences inherently provide
Gabriel Charettea3ccc972018-11-13 14:43:12274thread-safety. Prefer classes that are always accessed from the same
275sequence to managing your own thread-safety with locks.
276
277**Thread-safe but not thread-affine; how so?** Tasks posted to the same sequence
278will run in sequential order. After a sequenced task completes, the next task
279may be picked up by a different worker thread, but that task is guaranteed to
280see any side-effects caused by the previous one(s) on its sequence.
fdoraybacba4a22017-05-10 21:10:00281
282```cpp
283class A {
284 public:
285 A() {
286 // Do not require accesses to be on the creation sequence.
isherman8c33b8a2017-06-27 19:18:30287 DETACH_FROM_SEQUENCE(sequence_checker_);
fdoraybacba4a22017-05-10 21:10:00288 }
289
290 void AddValue(int v) {
291 // Check that all accesses are on the same sequence.
isherman8c33b8a2017-06-27 19:18:30292 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
fdoraybacba4a22017-05-10 21:10:00293 values_.push_back(v);
294}
295
296 private:
isherman8c33b8a2017-06-27 19:18:30297 SEQUENCE_CHECKER(sequence_checker_);
fdoraybacba4a22017-05-10 21:10:00298
299 // No lock required, because all accesses are on the
300 // same sequence.
301 std::vector<int> values_;
302};
303
304A a;
305scoped_refptr<SequencedTaskRunner> task_runner_for_a = ...;
Mike Bjorged3a09842018-05-15 18:37:28306task_runner_for_a->PostTask(FROM_HERE,
307 base::BindOnce(&A::AddValue, base::Unretained(&a), 42));
308task_runner_for_a->PostTask(FROM_HERE,
309 base::BindOnce(&A::AddValue, base::Unretained(&a), 27));
fdoraybacba4a22017-05-10 21:10:00310
311// Access from a different sequence causes a DCHECK failure.
312scoped_refptr<SequencedTaskRunner> other_task_runner = ...;
313other_task_runner->PostTask(FROM_HERE,
Mike Bjorged3a09842018-05-15 18:37:28314 base::BindOnce(&A::AddValue, base::Unretained(&a), 1));
fdoraybacba4a22017-05-10 21:10:00315```
316
Gabriel Charette90480312018-02-16 15:10:05317Locks should only be used to swap in a shared data structure that can be
318accessed on multiple threads. If one thread updates it based on expensive
319computation or through disk access, then that slow work should be done without
Gabriel Charette39db4c62019-04-29 19:52:38320holding the lock. Only when the result is available should the lock be used to
321swap in the new data. An example of this is in PluginList::LoadPlugins
322([`content/browser/plugin_list.cc`](https://cs.chromium.org/chromium/src/content/browser/plugin_list.cc).
323If you must use locks,
Gabriel Charette90480312018-02-16 15:10:05324[here](https://www.chromium.org/developers/lock-and-condition-variable) are some
325best practices and pitfalls to avoid.
326
Gabriel Charette39db4c62019-04-29 19:52:38327In order to write non-blocking code, many APIs in Chrome are asynchronous.
Gabriel Charette90480312018-02-16 15:10:05328Usually this means that they either need to be executed on a particular
329thread/sequence and will return results via a custom delegate interface, or they
Alex St-Onge490a97a2021-02-04 02:47:19330take a `base::OnceCallback<>` (or `base::RepeatingCallback<>`) object that is
331called when the requested operation is completed. Executing work on a specific
332thread/sequence is covered in the PostTask sections above.
Gabriel Charette90480312018-02-16 15:10:05333
fdoraybacba4a22017-05-10 21:10:00334## Posting Multiple Tasks to the Same Thread
335
336If multiple tasks need to run on the same thread, post them to a
Gabriel Charette39db4c62019-04-29 19:52:38337[`base::SingleThreadTaskRunner`](https://cs.chromium.org/chromium/src/base/single_thread_task_runner.h).
338All tasks posted to the same `base::SingleThreadTaskRunner` run on the same thread in
fdoraybacba4a22017-05-10 21:10:00339posting order.
340
341### Posting to the Main Thread or to the IO Thread in the Browser Process
342
Eric Seckler6cf08db82018-08-30 12:01:55343To post tasks to the main thread or to the IO thread, use
Olivier Li56b99d4e2020-02-11 13:51:41344`content::GetUIThreadTaskRunner({})` or `content::GetIOThreadTaskRunner({})`
Gabriel Charette49e3cd02020-01-28 03:45:27345from
346[`content/public/browser/browser_thread.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_thread.h)
347
348You may provide additional BrowserTaskTraits as a parameter to those methods
349though this is generally still uncommon in BrowserThreads and should be reserved
350for advanced use cases.
351
352There's an ongoing migration ([task APIs v3]) away from the previous
353base-API-with-traits which you may still find throughout the codebase (it's
354equivalent):
fdoraybacba4a22017-05-10 21:10:00355
356```cpp
Sami Kyostila831c60b2019-07-31 13:31:23357base::PostTask(FROM_HERE, {content::BrowserThread::UI}, ...);
fdoraybacba4a22017-05-10 21:10:00358
Sami Kyostila831c60b2019-07-31 13:31:23359base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
fdoraybacba4a22017-05-10 21:10:00360 ->PostTask(FROM_HERE, ...);
361```
362
Gabriel Charette49e3cd02020-01-28 03:45:27363Note: For the duration of the migration, you'll unfortunately need to continue
364manually including
365[`content/public/browser/browser_task_traits.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_task_traits.h).
366to use the browser_thread.h API.
Gabriel Charette43de5c42020-01-27 22:44:45367
fdoraybacba4a22017-05-10 21:10:00368The main thread and the IO thread are already super busy. Therefore, prefer
fdoray52bf5552017-05-11 12:43:59369posting to a general purpose thread when possible (ref.
370[Posting a Parallel Task](#Posting-a-Parallel-Task),
371[Posting a Sequenced task](#Posting-a-Sequenced-Task)).
372Good reasons to post to the main thread are to update the UI or access objects
373that are bound to it (e.g. `Profile`). A good reason to post to the IO thread is
374to access the internals of components that are bound to it (e.g. IPCs, network).
375Note: It is not necessary to have an explicit post task to the IO thread to
376send/receive an IPC or send/receive data on the network.
fdoraybacba4a22017-05-10 21:10:00377
378### Posting to the Main Thread in a Renderer Process
Gabriel Charette49e3cd02020-01-28 03:45:27379TODO(blink-dev)
fdoraybacba4a22017-05-10 21:10:00380
381### Posting to a Custom SingleThreadTaskRunner
382
383If multiple tasks need to run on the same thread and that thread doesn’t have to
Gabriel Charette43de5c42020-01-27 22:44:45384be the main thread or the IO thread, post them to a
Gabriel Charette49e3cd02020-01-28 03:45:27385`base::SingleThreadTaskRunner` created by
386`base::Threadpool::CreateSingleThreadTaskRunner`.
fdoraybacba4a22017-05-10 21:10:00387
388```cpp
Dominic Farolinodbe9769b2019-05-31 04:06:03389scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45390 base::Threadpool::CreateSingleThreadTaskRunner(...);
fdoraybacba4a22017-05-10 21:10:00391
392// TaskB runs after TaskA completes. Both tasks run on the same thread.
393single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
394single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
395```
396
Gabriel Charette39db4c62019-04-29 19:52:38397Remember that we [prefer sequences to physical
398threads](#prefer-sequences-to-physical-threads) and that this thus should rarely
399be necessary.
fdoraybacba4a22017-05-10 21:10:00400
Alexander Timine653dfc2020-01-07 17:55:06401### Posting to the Current Thread
402
403*** note
404**IMPORTANT:** To post a task that needs mutual exclusion with the current
Gabriel Charette49e3cd02020-01-28 03:45:27405sequence of tasks but doesn’t absolutely need to run on the current physical
406thread, use `base::SequencedTaskRunnerHandle::Get()` instead of
Alexander Timine653dfc2020-01-07 17:55:06407`base::ThreadTaskRunnerHandle::Get()` (ref. [Posting to the Current
Gabriel Charette49e3cd02020-01-28 03:45:27408Sequence](#Posting-to-the-Current-Virtual_Thread)). That will better document
409the requirements of the posted task and will avoid unnecessarily making your API
410physical thread-affine. In a single-thread task,
411`base::SequencedTaskRunnerHandle::Get()` is equivalent to
412`base::ThreadTaskRunnerHandle::Get()`.
Alexander Timine653dfc2020-01-07 17:55:06413***
414
415If you must post a task to the current physical thread nonetheless, use
416[`base::ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h).
417
418```cpp
419// The task will run on the current thread in the future.
420base::ThreadTaskRunnerHandle::Get()->PostTask(
421 FROM_HERE, base::BindOnce(&Task));
422```
423
fdoraybacba4a22017-05-10 21:10:00424## Posting Tasks to a COM Single-Thread Apartment (STA) Thread (Windows)
425
426Tasks that need to run on a COM Single-Thread Apartment (STA) thread must be
Gabriel Charette39db4c62019-04-29 19:52:38427posted to a `base::SingleThreadTaskRunner` returned by
Gabriel Charette43de5c42020-01-27 22:44:45428`base::ThreadPool::CreateCOMSTATaskRunner()`. As mentioned in [Posting Multiple
429Tasks to the Same Thread](#Posting-Multiple-Tasks-to-the-Same-Thread), all tasks
430posted to the same `base::SingleThreadTaskRunner` run on the same thread in
431posting order.
fdoraybacba4a22017-05-10 21:10:00432
433```cpp
434// Task(A|B|C)UsingCOMSTA will run on the same COM STA thread.
435
436void TaskAUsingCOMSTA() {
437 // [ This runs on a COM STA thread. ]
438
439 // Make COM STA calls.
440 // ...
441
442 // Post another task to the current COM STA thread.
443 base::ThreadTaskRunnerHandle::Get()->PostTask(
444 FROM_HERE, base::BindOnce(&TaskCUsingCOMSTA));
445}
446void TaskBUsingCOMSTA() { }
447void TaskCUsingCOMSTA() { }
448
Gabriel Charette43de5c42020-01-27 22:44:45449auto com_sta_task_runner = base::ThreadPool::CreateCOMSTATaskRunner(...);
fdoraybacba4a22017-05-10 21:10:00450com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskAUsingCOMSTA));
451com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskBUsingCOMSTA));
452```
453
454## Annotating Tasks with TaskTraits
455
Gabriel Charette39db4c62019-04-29 19:52:38456[`base::TaskTraits`](https://cs.chromium.org/chromium/src/base/task/task_traits.h)
Gabriel Charette52fa3ae2019-04-15 21:44:37457encapsulate information about a task that helps the thread pool make better
fdoraybacba4a22017-05-10 21:10:00458scheduling decisions.
459
Gabriel Charette43de5c42020-01-27 22:44:45460Methods that take `base::TaskTraits` can be be passed `{}` when default traits
461are sufficient. Default traits are appropriate for tasks that:
Gabriel Charettede41cad2020-03-03 18:05:06462- Don’t block (ref. MayBlock and WithBaseSyncPrimitives);
463- Pertain to user-blocking activity;
464 (explicitly or implicitly by having an ordering dependency with a component
465 that does)
Gabriel Charette52fa3ae2019-04-15 21:44:37466- Can either block shutdown or be skipped on shutdown (thread pool is free to
467 choose a fitting default).
fdoraybacba4a22017-05-10 21:10:00468Tasks that don’t match this description must be posted with explicit TaskTraits.
469
Gabriel Charette04b138f2018-08-06 00:03:22470[`base/task/task_traits.h`](https://cs.chromium.org/chromium/src/base/task/task_traits.h)
Eric Seckler6cf08db82018-08-30 12:01:55471provides exhaustive documentation of available traits. The content layer also
472provides additional traits in
473[`content/public/browser/browser_task_traits.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_task_traits.h)
474to facilitate posting a task onto a BrowserThread.
475
Gabriel Charette39db4c62019-04-29 19:52:38476Below are some examples of how to specify `base::TaskTraits`.
fdoraybacba4a22017-05-10 21:10:00477
478```cpp
Gabriel Charettede41cad2020-03-03 18:05:06479// This task has no explicit TaskTraits. It cannot block. Its priority is
480// USER_BLOCKING. It will either block shutdown or be skipped on shutdown.
Gabriel Charette43de5c42020-01-27 22:44:45481base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(...));
fdoraybacba4a22017-05-10 21:10:00482
Gabriel Charettede41cad2020-03-03 18:05:06483// This task has the highest priority. The thread pool will schedule it before
484// USER_VISIBLE and BEST_EFFORT tasks.
Gabriel Charette43de5c42020-01-27 22:44:45485base::ThreadPool::PostTask(
fdoraybacba4a22017-05-10 21:10:00486 FROM_HERE, {base::TaskPriority::USER_BLOCKING},
487 base::BindOnce(...));
488
489// This task has the lowest priority and is allowed to block (e.g. it
490// can read a file from disk).
Gabriel Charette43de5c42020-01-27 22:44:45491base::ThreadPool::PostTask(
Gabriel Charetteb10aeebc2018-07-26 20:15:00492 FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
fdoraybacba4a22017-05-10 21:10:00493 base::BindOnce(...));
494
495// This task blocks shutdown. The process won't exit before its
496// execution is complete.
Gabriel Charette43de5c42020-01-27 22:44:45497base::ThreadPool::PostTask(
fdoraybacba4a22017-05-10 21:10:00498 FROM_HERE, {base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
499 base::BindOnce(...));
500```
501
502## Keeping the Browser Responsive
503
504Do not perform expensive work on the main thread, the IO thread or any sequence
505that is expected to run tasks with a low latency. Instead, perform expensive
Gabriel Charette43de5c42020-01-27 22:44:45506work asynchronously using `base::ThreadPool::PostTaskAndReply*()` or
Gabriel Charette39db4c62019-04-29 19:52:38507`base::SequencedTaskRunner::PostTaskAndReply()`. Note that
508asynchronous/overlapped I/O on the IO thread are fine.
fdoraybacba4a22017-05-10 21:10:00509
510Example: Running the code below on the main thread will prevent the browser from
511responding to user input for a long time.
512
513```cpp
514// GetHistoryItemsFromDisk() may block for a long time.
515// AddHistoryItemsToOmniboxDropDown() updates the UI and therefore must
516// be called on the main thread.
517AddHistoryItemsToOmniboxDropdown(GetHistoryItemsFromDisk("keyword"));
518```
519
520The code below solves the problem by scheduling a call to
521`GetHistoryItemsFromDisk()` in a thread pool followed by a call to
522`AddHistoryItemsToOmniboxDropdown()` on the origin sequence (the main thread in
523this case). The return value of the first call is automatically provided as
524argument to the second call.
525
526```cpp
Gabriel Charette43de5c42020-01-27 22:44:45527base::ThreadPool::PostTaskAndReplyWithResult(
fdoraybacba4a22017-05-10 21:10:00528 FROM_HERE, {base::MayBlock()},
529 base::BindOnce(&GetHistoryItemsFromDisk, "keyword"),
530 base::BindOnce(&AddHistoryItemsToOmniboxDropdown));
531```
532
533## Posting a Task with a Delay
534
535### Posting a One-Off Task with a Delay
536
537To post a task that must run once after a delay expires, use
Gabriel Charette43de5c42020-01-27 22:44:45538`base::ThreadPool::PostDelayedTask*()` or `base::TaskRunner::PostDelayedTask()`.
fdoraybacba4a22017-05-10 21:10:00539
540```cpp
Gabriel Charette43de5c42020-01-27 22:44:45541base::ThreadPool::PostDelayedTask(
Gabriel Charetteb10aeebc2018-07-26 20:15:00542 FROM_HERE, {base::TaskPriority::BEST_EFFORT}, base::BindOnce(&Task),
fdoraybacba4a22017-05-10 21:10:00543 base::TimeDelta::FromHours(1));
544
545scoped_refptr<base::SequencedTaskRunner> task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45546 base::ThreadPool::CreateSequencedTaskRunner(
547 {base::TaskPriority::BEST_EFFORT});
fdoraybacba4a22017-05-10 21:10:00548task_runner->PostDelayedTask(
549 FROM_HERE, base::BindOnce(&Task), base::TimeDelta::FromHours(1));
550```
551
552*** note
553**NOTE:** A task that has a 1-hour delay probably doesn’t have to run right away
Gabriel Charetteb10aeebc2018-07-26 20:15:00554when its delay expires. Specify `base::TaskPriority::BEST_EFFORT` to prevent it
fdoraybacba4a22017-05-10 21:10:00555from slowing down the browser when its delay expires.
556***
557
558### Posting a Repeating Task with a Delay
559To post a task that must run at regular intervals,
560use [`base::RepeatingTimer`](https://cs.chromium.org/chromium/src/base/timer/timer.h).
561
562```cpp
563class A {
564 public:
565 ~A() {
566 // The timer is stopped automatically when it is deleted.
567 }
568 void StartDoingStuff() {
569 timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1),
Erik Chen0ee26a32021-07-14 20:04:47570 this, &A::DoStuff);
fdoraybacba4a22017-05-10 21:10:00571 }
572 void StopDoingStuff() {
573 timer_.Stop();
574 }
575 private:
576 void DoStuff() {
577 // This method is called every second on the sequence that invoked
578 // StartDoingStuff().
579 }
580 base::RepeatingTimer timer_;
581};
582```
583
584## Cancelling a Task
585
586### Using base::WeakPtr
587
588[`base::WeakPtr`](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h)
589can be used to ensure that any callback bound to an object is canceled when that
590object is destroyed.
591
592```cpp
593int Compute() { … }
594
595class A {
596 public:
fdoraybacba4a22017-05-10 21:10:00597 void ComputeAndStore() {
598 // Schedule a call to Compute() in a thread pool followed by
599 // a call to A::Store() on the current sequence. The call to
600 // A::Store() is canceled when |weak_ptr_factory_| is destroyed.
601 // (guarantees that |this| will not be used-after-free).
Gabriel Charette43de5c42020-01-27 22:44:45602 base::ThreadPool::PostTaskAndReplyWithResult(
fdoraybacba4a22017-05-10 21:10:00603 FROM_HERE, base::BindOnce(&Compute),
604 base::BindOnce(&A::Store, weak_ptr_factory_.GetWeakPtr()));
605 }
606
607 private:
608 void Store(int value) { value_ = value; }
609
610 int value_;
Jeremy Roman0dd0b2f2019-07-16 21:00:43611 base::WeakPtrFactory<A> weak_ptr_factory_{this};
fdoraybacba4a22017-05-10 21:10:00612};
613```
614
615Note: `WeakPtr` is not thread-safe: `GetWeakPtr()`, `~WeakPtrFactory()`, and
Francois Dorayf652a9d02021-07-06 13:07:52616`Store()` (bound to a `WeakPtr`) must all run on the same sequence.
fdoraybacba4a22017-05-10 21:10:00617
618### Using base::CancelableTaskTracker
619
620[`base::CancelableTaskTracker`](https://cs.chromium.org/chromium/src/base/task/cancelable_task_tracker.h)
621allows cancellation to happen on a different sequence than the one on which
622tasks run. Keep in mind that `CancelableTaskTracker` cannot cancel tasks that
623have already started to run.
624
625```cpp
Gabriel Charette43de5c42020-01-27 22:44:45626auto task_runner = base::ThreadPool::CreateTaskRunner({});
fdoraybacba4a22017-05-10 21:10:00627base::CancelableTaskTracker cancelable_task_tracker;
628cancelable_task_tracker.PostTask(task_runner.get(), FROM_HERE,
Peter Kasting341e1fb2018-02-24 00:03:01629 base::DoNothing());
fdoraybacba4a22017-05-10 21:10:00630// Cancels Task(), only if it hasn't already started running.
631cancelable_task_tracker.TryCancelAll();
632```
633
Etienne Pierre-dorayd3882992020-01-14 20:34:11634## Posting a Job to run in parallel
635
636The [`base::PostJob`](https://cs.chromium.org/chromium/src/base/task/post_job.h)
637is a power user API to be able to schedule a single base::RepeatingCallback
Albert J. Wongf06ff5002021-07-08 20:37:00638worker task and request that ThreadPool workers invoke it in parallel.
Etienne Pierre-dorayd3882992020-01-14 20:34:11639This avoids degenerate cases:
640* Calling `PostTask()` for each work item, causing significant overhead.
641* Fixed number of `PostTask()` calls that split the work and might run for a
642 long time. This is problematic when many components post “num cores” tasks and
643 all expect to use all the cores. In these cases, the scheduler lacks context
644 to be fair to multiple same-priority requests and/or ability to request lower
645 priority work to yield when high priority work comes in.
646
Etienne Pierre-doray6d3cd9192020-04-06 21:10:37647See [`base/task/job_perftest.cc`](https://cs.chromium.org/chromium/src/base/task/job_perftest.cc)
648for a complete example.
649
Etienne Pierre-dorayd3882992020-01-14 20:34:11650```cpp
651// A canonical implementation of |worker_task|.
652void WorkerTask(base::JobDelegate* job_delegate) {
653 while (!job_delegate->ShouldYield()) {
654 auto work_item = TakeWorkItem(); // Smallest unit of work.
655 if (!work_item)
656 return:
657 ProcessWork(work_item);
658 }
659}
660
661// Returns the latest thread-safe number of incomplete work items.
Etienne Pierre-Dorayf91d7a02020-09-11 15:53:27662void NumIncompleteWorkItems(size_t worker_count) {
663 // NumIncompleteWorkItems() may use |worker_count| if it needs to account for
664 // local work lists, which is easier than doing its own accounting, keeping in
665 // mind that the actual number of items may be racily overestimated and thus
666 // WorkerTask() may be called when there's no available work.
667 return GlobalQueueSize() + worker_count;
668}
Etienne Pierre-dorayd3882992020-01-14 20:34:11669
Gabriel Charette1138d602020-01-29 08:51:52670base::PostJob(FROM_HERE, {},
Etienne Pierre-dorayd3882992020-01-14 20:34:11671 base::BindRepeating(&WorkerTask),
672 base::BindRepeating(&NumIncompleteWorkItems));
673```
674
675By doing as much work as possible in a loop when invoked, the worker task avoids
676scheduling overhead. Meanwhile `base::JobDelegate::ShouldYield()` is
677periodically invoked to conditionally exit and let the scheduler prioritize
678other work. This yield-semantic allows, for example, a user-visible job to use
679all cores but get out of the way when a user-blocking task comes in.
680
Jared Saulea867ab2021-07-15 17:39:01681### Adding additional work to a running job
Etienne Pierre-dorayd3882992020-01-14 20:34:11682
683When new work items are added and the API user wants additional threads to
Albert J. Wongf06ff5002021-07-08 20:37:00684invoke the worker task in parallel,
Etienne Pierre-dorayd3882992020-01-14 20:34:11685`JobHandle/JobDelegate::NotifyConcurrencyIncrease()` *must* be invoked shortly
686after max concurrency increases.
687
fdoraybacba4a22017-05-10 21:10:00688## Testing
689
Gabriel Charette0b20ee6c2019-09-18 14:06:12690For more details see [Testing Components Which Post
691Tasks](threading_and_tasks_testing.md).
692
fdoraybacba4a22017-05-10 21:10:00693To test code that uses `base::ThreadTaskRunnerHandle`,
694`base::SequencedTaskRunnerHandle` or a function in
Gabriel Charette39db4c62019-04-29 19:52:38695[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h),
696instantiate a
Gabriel Charette0b20ee6c2019-09-18 14:06:12697[`base::test::TaskEnvironment`](https://cs.chromium.org/chromium/src/base/test/task_environment.h)
Gabriel Charette39db4c62019-04-29 19:52:38698for the scope of the test. If you need BrowserThreads, use
Gabriel Charette798fde72019-08-20 22:24:04699`content::BrowserTaskEnvironment` instead of
Gabriel Charette694c3c332019-08-19 14:53:05700`base::test::TaskEnvironment`.
fdoraybacba4a22017-05-10 21:10:00701
Gabriel Charette694c3c332019-08-19 14:53:05702Tests can run the `base::test::TaskEnvironment`'s message pump using a
Gabriel Charette39db4c62019-04-29 19:52:38703`base::RunLoop`, which can be made to run until `Quit()` (explicitly or via
704`RunLoop::QuitClosure()`), or to `RunUntilIdle()` ready-to-run tasks and
705immediately return.
Wezd9e4cb772019-01-09 03:07:03706
Wez9d5dd282020-02-10 17:21:22707TaskEnvironment configures RunLoop::Run() to GTEST_FAIL() if it hasn't been
Wezd9e4cb772019-01-09 03:07:03708explicitly quit after TestTimeouts::action_timeout(). This is preferable to
709having the test hang if the code under test fails to trigger the RunLoop to
Wez9d5dd282020-02-10 17:21:22710quit. The timeout can be overridden with base::test::ScopedRunLoopTimeout.
Wezd9e4cb772019-01-09 03:07:03711
fdoraybacba4a22017-05-10 21:10:00712```cpp
713class MyTest : public testing::Test {
714 public:
715 // ...
716 protected:
Gabriel Charette694c3c332019-08-19 14:53:05717 base::test::TaskEnvironment task_environment_;
fdoraybacba4a22017-05-10 21:10:00718};
719
720TEST(MyTest, MyTest) {
721 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&A));
722 base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
723 base::BindOnce(&B));
724 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
725 FROM_HERE, base::BindOnce(&C), base::TimeDelta::Max());
726
727 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until it is empty.
728 // Delayed tasks are not added to the queue until they are ripe for execution.
729 base::RunLoop().RunUntilIdle();
730 // A and B have been executed. C is not ripe for execution yet.
731
732 base::RunLoop run_loop;
733 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&D));
734 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
735 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&E));
736
737 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until QuitClosure is
738 // invoked.
739 run_loop.Run();
740 // D and run_loop.QuitClosure() have been executed. E is still in the queue.
741
Gabriel Charette52fa3ae2019-04-15 21:44:37742 // Tasks posted to thread pool run asynchronously as they are posted.
Gabriel Charette43de5c42020-01-27 22:44:45743 base::ThreadPool::PostTask(FROM_HERE, {}, base::BindOnce(&F));
fdoraybacba4a22017-05-10 21:10:00744 auto task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45745 base::ThreadPool::CreateSequencedTaskRunner({});
fdoraybacba4a22017-05-10 21:10:00746 task_runner->PostTask(FROM_HERE, base::BindOnce(&G));
747
Gabriel Charette52fa3ae2019-04-15 21:44:37748 // To block until all tasks posted to thread pool are done running:
Gabriel Charette43fd3702019-05-29 16:36:51749 base::ThreadPoolInstance::Get()->FlushForTesting();
fdoraybacba4a22017-05-10 21:10:00750 // F and G have been executed.
751
Gabriel Charette43de5c42020-01-27 22:44:45752 base::ThreadPool::PostTaskAndReplyWithResult(
753 FROM_HERE, {}, base::BindOnce(&H), base::BindOnce(&I));
fdoraybacba4a22017-05-10 21:10:00754
755 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until both the
756 // (Thread|Sequenced)TaskRunnerHandle queue and the TaskSchedule queue are
757 // empty:
Gabriel Charette694c3c332019-08-19 14:53:05758 task_environment_.RunUntilIdle();
fdoraybacba4a22017-05-10 21:10:00759 // E, H, I have been executed.
760}
761```
762
Gabriel Charette52fa3ae2019-04-15 21:44:37763## Using ThreadPool in a New Process
fdoraybacba4a22017-05-10 21:10:00764
Gabriel Charette43fd3702019-05-29 16:36:51765ThreadPoolInstance needs to be initialized in a process before the functions in
Gabriel Charette04b138f2018-08-06 00:03:22766[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h)
Gabriel Charette43fd3702019-05-29 16:36:51767can be used. Initialization of ThreadPoolInstance in the Chrome browser process
768and child processes (renderer, GPU, utility) has already been taken care of. To
769use ThreadPoolInstance in another process, initialize ThreadPoolInstance early
770in the main function:
fdoraybacba4a22017-05-10 21:10:00771
772```cpp
Gabriel Charette43fd3702019-05-29 16:36:51773// This initializes and starts ThreadPoolInstance with default params.
774base::ThreadPoolInstance::CreateAndStartWithDefaultParams(“process_name”);
775// The base/task/post_task.h API can now be used with base::ThreadPool trait.
Jared Saulea867ab2021-07-15 17:39:01776// Tasks will be scheduled as they are posted.
fdoraybacba4a22017-05-10 21:10:00777
Gabriel Charette43fd3702019-05-29 16:36:51778// This initializes ThreadPoolInstance.
779base::ThreadPoolInstance::Create(“process_name”);
780// The base/task/post_task.h API can now be used with base::ThreadPool trait. No
781// threads will be created and no tasks will be scheduled until after Start() is
782// called.
783base::ThreadPoolInstance::Get()->Start(params);
Gabriel Charette52fa3ae2019-04-15 21:44:37784// ThreadPool can now create threads and schedule tasks.
fdoraybacba4a22017-05-10 21:10:00785```
786
Gabriel Charette43fd3702019-05-29 16:36:51787And shutdown ThreadPoolInstance late in the main function:
fdoraybacba4a22017-05-10 21:10:00788
789```cpp
Gabriel Charette43fd3702019-05-29 16:36:51790base::ThreadPoolInstance::Get()->Shutdown();
fdoraybacba4a22017-05-10 21:10:00791// Tasks posted with TaskShutdownBehavior::BLOCK_SHUTDOWN and
792// tasks posted with TaskShutdownBehavior::SKIP_ON_SHUTDOWN that
793// have started to run before the Shutdown() call have now completed their
794// execution. Tasks posted with
795// TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN may still be
796// running.
797```
Gabriel Charetteb86e5fe62017-06-08 19:39:28798## TaskRunner ownership (encourage no dependency injection)
Sebastien Marchandc95489b2017-05-25 16:39:34799
800TaskRunners shouldn't be passed through several components. Instead, the
Jared Saulea867ab2021-07-15 17:39:01801component that uses a TaskRunner should be the one that creates it.
Sebastien Marchandc95489b2017-05-25 16:39:34802
803See [this example](https://codereview.chromium.org/2885173002/) of a
804refactoring where a TaskRunner was passed through a lot of components only to be
805used in an eventual leaf. The leaf can and should now obtain its TaskRunner
806directly from
Gabriel Charette04b138f2018-08-06 00:03:22807[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h).
Gabriel Charetteb86e5fe62017-06-08 19:39:28808
Gabriel Charette694c3c332019-08-19 14:53:05809As mentioned above, `base::test::TaskEnvironment` allows unit tests to
Gabriel Charette39db4c62019-04-29 19:52:38810control tasks posted from underlying TaskRunners. In rare cases where a test
811needs to more precisely control task ordering: dependency injection of
812TaskRunners can be useful. For such cases the preferred approach is the
813following:
Gabriel Charetteb86e5fe62017-06-08 19:39:28814
815```cpp
Gabriel Charette39db4c62019-04-29 19:52:38816class Foo {
Gabriel Charetteb86e5fe62017-06-08 19:39:28817 public:
818
Gabriel Charette39db4c62019-04-29 19:52:38819 // Overrides |background_task_runner_| in tests.
Gabriel Charetteb86e5fe62017-06-08 19:39:28820 void SetBackgroundTaskRunnerForTesting(
Gabriel Charette39db4c62019-04-29 19:52:38821 scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
822 background_task_runner_ = std::move(background_task_runner);
823 }
Gabriel Charetteb86e5fe62017-06-08 19:39:28824
825 private:
michaelpg12c04572017-06-26 23:25:06826 scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
Gabriel Charette43de5c42020-01-27 22:44:45827 base::ThreadPool::CreateSequencedTaskRunner(
Gabriel Charetteb10aeebc2018-07-26 20:15:00828 {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
Gabriel Charetteb86e5fe62017-06-08 19:39:28829}
830```
831
832Note that this still allows removing all layers of plumbing between //chrome and
833that component since unit tests will use the leaf layer directly.
Gabriel Charette8917f4c2018-11-22 15:50:28834
835## FAQ
836See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more examples.
Gabriel Charette43de5c42020-01-27 22:44:45837
838[task APIs v3]: https://docs.google.com/document/d/1tssusPykvx3g0gvbvU4HxGyn3MjJlIylnsH13-Tv6s4/edit?ts=5de99a52#heading=h.ss4tw38hvh3s
Carlos Caballero40b6d042020-06-16 06:50:25839
840## Internals
841
842### SequenceManager
843
844[SequenceManager](https://cs.chromium.org/chromium/src/base/task/sequence_manager/sequence_manager.h)
845manages TaskQueues which have different properties (e.g. priority, common task
846type) multiplexing all posted tasks into a single backing sequence. This will
847usually be a MessagePump. Depending on the type of message pump used other
848events such as UI messages may be processed as well. On Windows APC calls (as
849time permits) and signals sent to a registered set of HANDLEs may also be
850processed.
851
Carlos Caballero4a050922020-07-02 11:43:38852### MessagePump
Carlos Caballero40b6d042020-06-16 06:50:25853
854[MessagePumps](https://cs.chromium.org/chromium/src/base/message_loop/message_pump.h)
855are responsible for processing native messages as well as for giving cycles to
856their delegate (SequenceManager) periodically. MessagePumps take care to mixing
857delegate callbacks with native message processing so neither type of event
858starves the other of cycles.
859
860There are different [MessagePumpTypes](https://cs.chromium.org/chromium/src/base/message_loop/message_pump_type.h),
861most common are:
862
863* DEFAULT: Supports tasks and timers only
864
865* UI: Supports native UI events (e.g. Windows messages)
866
867* IO: Supports asynchronous IO (not file I/O!)
868
869* CUSTOM: User provided implementation of MessagePump interface
870
Carlos Caballero4a050922020-07-02 11:43:38871### RunLoop
Carlos Caballero40b6d042020-06-16 06:50:25872
Jared Saulea867ab2021-07-15 17:39:01873RunLoop is a helper class to run the RunLoop::Delegate associated with the
Carlos Caballero40b6d042020-06-16 06:50:25874current thread (usually a SequenceManager). Create a RunLoop on the stack and
875call Run/Quit to run a nested RunLoop but please avoid nested loops in
876production code!
877
Carlos Caballero4a050922020-07-02 11:43:38878### Task Reentrancy
Carlos Caballero40b6d042020-06-16 06:50:25879
880SequenceManager has task reentrancy protection. This means that if a
881task is being processed, a second task cannot start until the first task is
882finished. Reentrancy can happen when processing a task, and an inner
883message pump is created. That inner pump then processes native messages
884which could implicitly start an inner task. Inner message pumps are created
885with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
886(DoDragDrop), printer functions (StartDoc) and *many* others.
887
888```cpp
889Sample workaround when inner task processing is needed:
890 HRESULT hr;
891 {
Carlos Caballerob25fe8472020-07-17 10:27:17892 CurrentThread::ScopedNestableTaskAllower allow;
Carlos Caballero40b6d042020-06-16 06:50:25893 hr = DoDragDrop(...); // Implicitly runs a modal message loop.
894 }
895 // Process |hr| (the result returned by DoDragDrop()).
896```
897
898Please be SURE your task is reentrant (nestable) and all global variables
899are stable and accessible before before using
Carlos Caballerob25fe8472020-07-17 10:27:17900CurrentThread::ScopedNestableTaskAllower.
Carlos Caballero40b6d042020-06-16 06:50:25901
902## APIs for general use
903
904User code should hardly ever need to access SequenceManager APIs directly as
905these are meant for code that deals with scheduling. Instead you should use the
906following:
907
908* base::RunLoop: Drive the SequenceManager from the thread it's bound to.
909
910* base::Thread/SequencedTaskRunnerHandle: Post back to the SequenceManager TaskQueues from a task running on it.
911
912* SequenceLocalStorageSlot : Bind external state to a sequence.
913
Carlos Caballero4a050922020-07-02 11:43:38914* base::CurrentThread : Proxy to a subset of Task related APIs bound to the current thread
Carlos Caballero40b6d042020-06-16 06:50:25915
916* Embedders may provide their own static accessors to post tasks on specific loops (e.g. content::BrowserThreads).
917
918### SingleThreadTaskExecutor and TaskEnvironment
919
920Instead of having to deal with SequenceManager and TaskQueues code that needs a
921simple task posting environment (one default task queue) can use a
922[SingleThreadTaskExecutor](https://cs.chromium.org/chromium/src/base/task/single_thread_task_executor.h).
923
924Unit tests can use [TaskEnvironment](https://cs.chromium.org/chromium/src/base/test/task_environment.h)
925which is highly configurable.
Carlos Caballero4a050922020-07-02 11:43:38926
Wen Fane09439ca2021-03-09 16:50:41927## MessageLoop and MessageLoopCurrent
Carlos Caballero4a050922020-07-02 11:43:38928
Wen Fane09439ca2021-03-09 16:50:41929You might come across references to MessageLoop or MessageLoopCurrent in the
Carlos Caballero4a050922020-07-02 11:43:38930code or documentation. These classes no longer exist and we are in the process
Jared Saulea867ab2021-07-15 17:39:01931or getting rid of all references to them. `base::MessageLoopCurrent` was
932replaced by `base::CurrentThread` and the drop in replacements for
933`base::MessageLoop` are `base::SingleThreadTaskExecutor` and
934`base::Test::TaskEnvironment`.