blob: cf6335cb8dfa56d2fe13f7537ee051d2b7efe2bb [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
21messages between those threads for communication.
22
23This documentation assumes familiarity with computer science
24[threading concepts](https://en.wikipedia.org/wiki/Thread_(computing)).
Gabriel Charette90480312018-02-16 15:10:0525
Gabriel Charette364a16a2019-02-06 21:12:1526### Nomenclature
Gabriel Charette39db4c62019-04-29 19:52:3827
28## Core Concepts
29 * **Task**: A unit of work to be processed. Effectively a function pointer with
Alex St-Onge490a97a2021-02-04 02:47:1930 optionally associated state. In Chrome this is `base::OnceCallback` and
31 `base::RepeatingCallback` created via `base::BindOnce` and
32 `base::BindRepeating`, respectively.
Gabriel Charette39db4c62019-04-29 19:52:3833 ([documentation](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/callback.md)).
34 * **Task queue**: A queue of tasks to be processed.
35 * **Physical thread**: An operating system provided thread (e.g. pthread on
36 POSIX or CreateThread() on Windows). The Chrome cross-platform abstraction
37 is `base::PlatformThread`. You should pretty much never use this directly.
38 * **`base::Thread`**: A physical thread forever processing messages from a
39 dedicated task queue until Quit(). You should pretty much never be creating
40 your own `base::Thread`'s.
41 * **Thread pool**: A pool of physical threads with a shared task queue. In
Gabriel Charette0b20ee6c2019-09-18 14:06:1242 Chrome, this is `base::ThreadPoolInstance`. There's exactly one instance per
43 Chrome process, it serves tasks posted through
Gabriel Charette39db4c62019-04-29 19:52:3844 [`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h)
Gabriel Charette43fd3702019-05-29 16:36:5145 and as such you should rarely need to use the `base::ThreadPoolInstance` API
Gabriel Charette39db4c62019-04-29 19:52:3846 directly (more on posting tasks later).
47 * **Sequence** or **Virtual thread**: A chrome-managed thread of execution.
48 Like a physical thread, only one task can run on a given sequence / virtual
49 thread at any given moment and each task sees the side-effects of the
50 preceding tasks. Tasks are executed sequentially but may hop physical
51 threads between each one.
52 * **Task runner**: An interface through which tasks can be posted. In Chrome
53 this is `base::TaskRunner`.
54 * **Sequenced task runner**: A task runner which guarantees that tasks posted
55 to it will run sequentially, in posted order. Each such task is guaranteed to
56 see the side-effects of the task preceding it. Tasks posted to a sequenced
57 task runner are typically processed by a single thread (virtual or physical).
58 In Chrome this is `base::SequencedTaskRunner` which is-a
59 `base::TaskRunner`.
60 * **Single-thread task runner**: A sequenced task runner which guarantees that
61 all tasks will be processed by the same physical thread. In Chrome this is
62 `base::SingleThreadTaskRunner` which is-a `base::SequencedTaskRunner`. We
63 [prefer sequences to threads](#prefer-sequences-to-physical-threads) whenever
64 possible.
65
66## Threading Lexicon
67Note to the reader: the following terms are an attempt to bridge the gap between
68common threading nomenclature and the way we use them in Chrome. It might be a
69bit heavy if you're just getting started. Should this be hard to parse, consider
70skipping to the more detailed sections below and referring back to this as
71necessary.
72
73 * **Thread-unsafe**: The vast majority of types in Chrome are thread-unsafe
74 (by design). Access to such types/methods must be externally synchronized.
75 Typically thread-unsafe types require that all tasks accessing their state be
76 posted to the same `base::SequencedTaskRunner` and they verify this in debug
77 builds with a `SEQUENCE_CHECKER` member. Locks are also an option to
78 synchronize access but in Chrome we strongly
79 [prefer sequences to locks](#Using-Sequences-Instead-of-Locks).
Gabriel Charette364a16a2019-02-06 21:12:1580 * **Thread-affine**: Such types/methods need to be always accessed from the
Gabriel Charetteb984d672019-02-12 21:53:2781 same physical thread (i.e. from the same `base::SingleThreadTaskRunner`) and
Gabriel Charette39db4c62019-04-29 19:52:3882 typically have a `THREAD_CHECKER` member to verify that they are. Short of
83 using a third-party API or having a leaf dependency which is thread-affine:
84 there's pretty much no reason for a type to be thread-affine in Chrome.
85 Note that `base::SingleThreadTaskRunner` is-a `base::SequencedTaskRunner` so
Gabriel Charetteb984d672019-02-12 21:53:2786 thread-affine is a subset of thread-unsafe. Thread-affine is also sometimes
87 referred to as **thread-hostile**.
Gabriel Charette364a16a2019-02-06 21:12:1588 * **Thread-safe**: Such types/methods can be safely accessed concurrently.
Gabriel Charetteb984d672019-02-12 21:53:2789 * **Thread-compatible**: Such types provide safe concurrent access to const
90 methods but require synchronization for non-const (or mixed const/non-const
Gabriel Charette39db4c62019-04-29 19:52:3891 access). Chrome doesn't expose reader-writer locks; as such, the only use
Gabriel Charetteb984d672019-02-12 21:53:2792 case for this is objects (typically globals) which are initialized once in a
Gabriel Charette364a16a2019-02-06 21:12:1593 thread-safe manner (either in the single-threaded phase of startup or lazily
94 through a thread-safe static-local-initialization paradigm a la
Gabriel Charetteb984d672019-02-12 21:53:2795 `base::NoDestructor`) and forever after immutable.
96 * **Immutable**: A subset of thread-compatible types which cannot be modified
97 after construction.
Gabriel Charette364a16a2019-02-06 21:12:1598 * **Sequence-friendly**: Such types/methods are thread-unsafe types which
99 support being invoked from a `base::SequencedTaskRunner`. Ideally this would
100 be the case for all thread-unsafe types but legacy code sometimes has
101 overzealous checks that enforce thread-affinity in mere thread-unsafe
Gabriel Charette39db4c62019-04-29 19:52:38102 scenarios. See [Prefer Sequences to
103 Threads](#prefer-sequences-to-physical-threads) below for more details.
Gabriel Charette364a16a2019-02-06 21:12:15104
fdoraybacba4a22017-05-10 21:10:00105### Threads
106
107Every Chrome process has
108
109* a main thread
Gabriel Charette39db4c62019-04-29 19:52:38110 * in the browser process (BrowserThread::UI): updates the UI
111 * in renderer processes (Blink main thread): runs most of Blink
fdoraybacba4a22017-05-10 21:10:00112* an IO thread
Gabriel Charette49e3cd02020-01-28 03:45:27113 * in the browser process (BrowserThread::IO): handles IPCs and network
114 requests
fdoraybacba4a22017-05-10 21:10:00115 * in renderer processes: handles IPCs
116* a few more special-purpose threads
117* and a pool of general-purpose threads
118
119Most threads have a loop that gets tasks from a queue and runs them (the queue
120may be shared between multiple threads).
121
122### Tasks
123
124A task is a `base::OnceClosure` added to a queue for asynchronous execution.
125
126A `base::OnceClosure` stores a function pointer and arguments. It has a `Run()`
127method that invokes the function pointer using the bound arguments. It is
128created using `base::BindOnce`. (ref. [Callback<> and Bind()
129documentation](callback.md)).
130
131```
132void TaskA() {}
133void TaskB(int v) {}
134
135auto task_a = base::BindOnce(&TaskA);
136auto task_b = base::BindOnce(&TaskB, 42);
137```
138
139A group of tasks can be executed in one of the following ways:
140
141* [Parallel](#Posting-a-Parallel-Task): No task execution ordering, possibly all
142 at once on any thread
143* [Sequenced](#Posting-a-Sequenced-Task): Tasks executed in posting order, one
144 at a time on any thread.
145* [Single Threaded](#Posting-Multiple-Tasks-to-the-Same-Thread): Tasks executed
146 in posting order, one at a time on a single thread.
Drew Stonebraker653a3ba2019-07-02 19:24:23147 * [COM Single Threaded](#Posting-Tasks-to-a-COM-Single_Thread-Apartment-STA_Thread-Windows):
fdoraybacba4a22017-05-10 21:10:00148 A variant of single threaded with COM initialized.
149
Gabriel Charette39db4c62019-04-29 19:52:38150### Prefer Sequences to Physical Threads
gab2a4576052017-06-07 23:36:12151
Gabriel Charette39db4c62019-04-29 19:52:38152Sequenced execution (on virtual threads) is strongly preferred to
153single-threaded execution (on physical threads). Except for types/methods bound
154to the main thread (UI) or IO threads: thread-safety is better achieved via
155`base::SequencedTaskRunner` than through managing your own physical threads
156(ref. [Posting a Sequenced Task](#posting-a-sequenced-task) below).
gab2a4576052017-06-07 23:36:12157
Gabriel Charette39db4c62019-04-29 19:52:38158All APIs which are exposed for "current physical thread" have an equivalent for
159"current sequence"
160([mapping](threading_and_tasks_faq.md#How-to-migrate-from-SingleThreadTaskRunner-to-SequencedTaskRunner)).
gab2a4576052017-06-07 23:36:12161
Gabriel Charette39db4c62019-04-29 19:52:38162If you find yourself writing a sequence-friendly type and it fails
163thread-affinity checks (e.g., `THREAD_CHECKER`) in a leaf dependency: consider
164making that dependency sequence-friendly as well. Most core APIs in Chrome are
165sequence-friendly, but some legacy types may still over-zealously use
166ThreadChecker/ThreadTaskRunnerHandle/SingleThreadTaskRunner when they could
167instead rely on the "current sequence" and no longer be thread-affine.
fdoraybacba4a22017-05-10 21:10:00168
169## Posting a Parallel Task
170
Gabriel Charette52fa3ae2019-04-15 21:44:37171### Direct Posting to the Thread Pool
fdoraybacba4a22017-05-10 21:10:00172
173A task that can run on any thread and doesn’t have ordering or mutual exclusion
174requirements with other tasks should be posted using one of the
Gabriel Charette43de5c42020-01-27 22:44:45175`base::ThreadPool::PostTask*()` functions defined in
176[`base/task/thread_pool.h`](https://cs.chromium.org/chromium/src/base/task/thread_pool.h).
fdoraybacba4a22017-05-10 21:10:00177
178```cpp
Gabriel Charette43de5c42020-01-27 22:44:45179base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(&Task));
fdoraybacba4a22017-05-10 21:10:00180```
181
182This posts tasks with default traits.
183
Gabriel Charette43de5c42020-01-27 22:44:45184The `base::ThreadPool::PostTask*()` functions allow the caller to provide
185additional details about the task via TaskTraits (ref. [Annotating Tasks with
186TaskTraits](#Annotating-Tasks-with-TaskTraits)).
fdoraybacba4a22017-05-10 21:10:00187
188```cpp
Gabriel Charette43de5c42020-01-27 22:44:45189base::ThreadPool::PostTask(
Gabriel Charetteb10aeebc2018-07-26 20:15:00190 FROM_HERE, {base::TaskPriority::BEST_EFFORT, MayBlock()},
fdoraybacba4a22017-05-10 21:10:00191 base::BindOnce(&Task));
192```
193
fdoray52bf5552017-05-11 12:43:59194### Posting via a TaskRunner
fdoraybacba4a22017-05-10 21:10:00195
196A parallel
Gabriel Charette39db4c62019-04-29 19:52:38197[`base::TaskRunner`](https://cs.chromium.org/chromium/src/base/task_runner.h) is
Gabriel Charette43de5c42020-01-27 22:44:45198an alternative to calling `base::ThreadPool::PostTask*()` directly. This is
199mainly useful when it isn’t known in advance whether tasks will be posted in
200parallel, in sequence, or to a single-thread (ref. [Posting a Sequenced
Gabriel Charette39db4c62019-04-29 19:52:38201Task](#Posting-a-Sequenced-Task), [Posting Multiple Tasks to the Same
202Thread](#Posting-Multiple-Tasks-to-the-Same-Thread)). Since `base::TaskRunner`
203is the base class of `base::SequencedTaskRunner` and
204`base::SingleThreadTaskRunner`, a `scoped_refptr<TaskRunner>` member can hold a
205`base::TaskRunner`, a `base::SequencedTaskRunner` or a
206`base::SingleThreadTaskRunner`.
fdoraybacba4a22017-05-10 21:10:00207
208```cpp
209class A {
210 public:
211 A() = default;
212
Gabriel Charette43de5c42020-01-27 22:44:45213 void PostSomething() {
214 task_runner_->PostTask(FROM_HERE, base::BindOnce(&A, &DoSomething));
215 }
216
fdoraybacba4a22017-05-10 21:10:00217 void DoSomething() {
fdoraybacba4a22017-05-10 21:10:00218 }
219
220 private:
221 scoped_refptr<base::TaskRunner> task_runner_ =
Gabriel Charette43de5c42020-01-27 22:44:45222 base::ThreadPool::CreateTaskRunner({base::TaskPriority::USER_VISIBLE});
fdoraybacba4a22017-05-10 21:10:00223};
224```
225
226Unless a test needs to control precisely how tasks are executed, it is preferred
Gabriel Charette49e3cd02020-01-28 03:45:27227to call `base::ThreadPool::PostTask*()` directly (ref. [Testing](#Testing) for
228less invasive ways of controlling tasks in tests).
fdoraybacba4a22017-05-10 21:10:00229
230## Posting a Sequenced Task
231
232A sequence is a set of tasks that run one at a time in posting order (not
233necessarily on the same thread). To post tasks as part of a sequence, use a
Gabriel Charette39db4c62019-04-29 19:52:38234[`base::SequencedTaskRunner`](https://cs.chromium.org/chromium/src/base/sequenced_task_runner.h).
fdoraybacba4a22017-05-10 21:10:00235
236### Posting to a New Sequence
237
Gabriel Charette39db4c62019-04-29 19:52:38238A `base::SequencedTaskRunner` can be created by
Gabriel Charette43de5c42020-01-27 22:44:45239`base::ThreadPool::CreateSequencedTaskRunner()`.
fdoraybacba4a22017-05-10 21:10:00240
241```cpp
242scoped_refptr<SequencedTaskRunner> sequenced_task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45243 base::ThreadPool::CreateSequencedTaskRunner(...);
fdoraybacba4a22017-05-10 21:10:00244
245// TaskB runs after TaskA completes.
246sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
247sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
248```
249
Alex Clarke0dd499562019-10-18 19:45:09250### Posting to the Current (Virtual) Thread
251
Gabriel Charettefee55662019-11-20 21:06:28252The preferred way of posting to the current (virtual) thread is via
253`base::SequencedTaskRunnerHandle::Get()`.
Alex Clarke0dd499562019-10-18 19:45:09254
255```cpp
256// The task will run on the current (virtual) thread's default task queue.
Gabriel Charettefee55662019-11-20 21:06:28257base::SequencedTaskRunnerHandle::Get()->PostTask(
258 FROM_HERE, base::BindOnce(&Task);
Alex Clarke0dd499562019-10-18 19:45:09259```
260
Gabriel Charettefee55662019-11-20 21:06:28261Note that SequencedTaskRunnerHandle::Get() returns the default queue for the
262current virtual thread. On threads with multiple task queues (e.g.
263BrowserThread::UI) this can be a different queue than the one the current task
264belongs to. The "current" task runner is intentionally not exposed via a static
265getter. Either you know it already and can post to it directly or you don't and
266the only sensible destination is the default queue.
Alex Clarke0dd499562019-10-18 19:45:09267
fdoraybacba4a22017-05-10 21:10:00268## Using Sequences Instead of Locks
269
270Usage of locks is discouraged in Chrome. Sequences inherently provide
Gabriel Charettea3ccc972018-11-13 14:43:12271thread-safety. Prefer classes that are always accessed from the same
272sequence to managing your own thread-safety with locks.
273
274**Thread-safe but not thread-affine; how so?** Tasks posted to the same sequence
275will run in sequential order. After a sequenced task completes, the next task
276may be picked up by a different worker thread, but that task is guaranteed to
277see any side-effects caused by the previous one(s) on its sequence.
fdoraybacba4a22017-05-10 21:10:00278
279```cpp
280class A {
281 public:
282 A() {
283 // Do not require accesses to be on the creation sequence.
isherman8c33b8a2017-06-27 19:18:30284 DETACH_FROM_SEQUENCE(sequence_checker_);
fdoraybacba4a22017-05-10 21:10:00285 }
286
287 void AddValue(int v) {
288 // Check that all accesses are on the same sequence.
isherman8c33b8a2017-06-27 19:18:30289 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_);
fdoraybacba4a22017-05-10 21:10:00290 values_.push_back(v);
291}
292
293 private:
isherman8c33b8a2017-06-27 19:18:30294 SEQUENCE_CHECKER(sequence_checker_);
fdoraybacba4a22017-05-10 21:10:00295
296 // No lock required, because all accesses are on the
297 // same sequence.
298 std::vector<int> values_;
299};
300
301A a;
302scoped_refptr<SequencedTaskRunner> task_runner_for_a = ...;
Mike Bjorged3a09842018-05-15 18:37:28303task_runner_for_a->PostTask(FROM_HERE,
304 base::BindOnce(&A::AddValue, base::Unretained(&a), 42));
305task_runner_for_a->PostTask(FROM_HERE,
306 base::BindOnce(&A::AddValue, base::Unretained(&a), 27));
fdoraybacba4a22017-05-10 21:10:00307
308// Access from a different sequence causes a DCHECK failure.
309scoped_refptr<SequencedTaskRunner> other_task_runner = ...;
310other_task_runner->PostTask(FROM_HERE,
Mike Bjorged3a09842018-05-15 18:37:28311 base::BindOnce(&A::AddValue, base::Unretained(&a), 1));
fdoraybacba4a22017-05-10 21:10:00312```
313
Gabriel Charette90480312018-02-16 15:10:05314Locks should only be used to swap in a shared data structure that can be
315accessed on multiple threads. If one thread updates it based on expensive
316computation or through disk access, then that slow work should be done without
Gabriel Charette39db4c62019-04-29 19:52:38317holding the lock. Only when the result is available should the lock be used to
318swap in the new data. An example of this is in PluginList::LoadPlugins
319([`content/browser/plugin_list.cc`](https://cs.chromium.org/chromium/src/content/browser/plugin_list.cc).
320If you must use locks,
Gabriel Charette90480312018-02-16 15:10:05321[here](https://www.chromium.org/developers/lock-and-condition-variable) are some
322best practices and pitfalls to avoid.
323
Gabriel Charette39db4c62019-04-29 19:52:38324In order to write non-blocking code, many APIs in Chrome are asynchronous.
Gabriel Charette90480312018-02-16 15:10:05325Usually this means that they either need to be executed on a particular
326thread/sequence and will return results via a custom delegate interface, or they
Alex St-Onge490a97a2021-02-04 02:47:19327take a `base::OnceCallback<>` (or `base::RepeatingCallback<>`) object that is
328called when the requested operation is completed. Executing work on a specific
329thread/sequence is covered in the PostTask sections above.
Gabriel Charette90480312018-02-16 15:10:05330
fdoraybacba4a22017-05-10 21:10:00331## Posting Multiple Tasks to the Same Thread
332
333If multiple tasks need to run on the same thread, post them to a
Gabriel Charette39db4c62019-04-29 19:52:38334[`base::SingleThreadTaskRunner`](https://cs.chromium.org/chromium/src/base/single_thread_task_runner.h).
335All tasks posted to the same `base::SingleThreadTaskRunner` run on the same thread in
fdoraybacba4a22017-05-10 21:10:00336posting order.
337
338### Posting to the Main Thread or to the IO Thread in the Browser Process
339
Eric Seckler6cf08db82018-08-30 12:01:55340To post tasks to the main thread or to the IO thread, use
Olivier Li56b99d4e2020-02-11 13:51:41341`content::GetUIThreadTaskRunner({})` or `content::GetIOThreadTaskRunner({})`
Gabriel Charette49e3cd02020-01-28 03:45:27342from
343[`content/public/browser/browser_thread.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_thread.h)
344
345You may provide additional BrowserTaskTraits as a parameter to those methods
346though this is generally still uncommon in BrowserThreads and should be reserved
347for advanced use cases.
348
349There's an ongoing migration ([task APIs v3]) away from the previous
350base-API-with-traits which you may still find throughout the codebase (it's
351equivalent):
fdoraybacba4a22017-05-10 21:10:00352
353```cpp
Sami Kyostila831c60b2019-07-31 13:31:23354base::PostTask(FROM_HERE, {content::BrowserThread::UI}, ...);
fdoraybacba4a22017-05-10 21:10:00355
Sami Kyostila831c60b2019-07-31 13:31:23356base::CreateSingleThreadTaskRunner({content::BrowserThread::IO})
fdoraybacba4a22017-05-10 21:10:00357 ->PostTask(FROM_HERE, ...);
358```
359
Gabriel Charette49e3cd02020-01-28 03:45:27360Note: For the duration of the migration, you'll unfortunately need to continue
361manually including
362[`content/public/browser/browser_task_traits.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_task_traits.h).
363to use the browser_thread.h API.
Gabriel Charette43de5c42020-01-27 22:44:45364
fdoraybacba4a22017-05-10 21:10:00365The main thread and the IO thread are already super busy. Therefore, prefer
fdoray52bf5552017-05-11 12:43:59366posting to a general purpose thread when possible (ref.
367[Posting a Parallel Task](#Posting-a-Parallel-Task),
368[Posting a Sequenced task](#Posting-a-Sequenced-Task)).
369Good reasons to post to the main thread are to update the UI or access objects
370that are bound to it (e.g. `Profile`). A good reason to post to the IO thread is
371to access the internals of components that are bound to it (e.g. IPCs, network).
372Note: It is not necessary to have an explicit post task to the IO thread to
373send/receive an IPC or send/receive data on the network.
fdoraybacba4a22017-05-10 21:10:00374
375### Posting to the Main Thread in a Renderer Process
Gabriel Charette49e3cd02020-01-28 03:45:27376TODO(blink-dev)
fdoraybacba4a22017-05-10 21:10:00377
378### Posting to a Custom SingleThreadTaskRunner
379
380If multiple tasks need to run on the same thread and that thread doesn’t have to
Gabriel Charette43de5c42020-01-27 22:44:45381be the main thread or the IO thread, post them to a
Gabriel Charette49e3cd02020-01-28 03:45:27382`base::SingleThreadTaskRunner` created by
383`base::Threadpool::CreateSingleThreadTaskRunner`.
fdoraybacba4a22017-05-10 21:10:00384
385```cpp
Dominic Farolinodbe9769b2019-05-31 04:06:03386scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45387 base::Threadpool::CreateSingleThreadTaskRunner(...);
fdoraybacba4a22017-05-10 21:10:00388
389// TaskB runs after TaskA completes. Both tasks run on the same thread.
390single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
391single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
392```
393
Gabriel Charette39db4c62019-04-29 19:52:38394Remember that we [prefer sequences to physical
395threads](#prefer-sequences-to-physical-threads) and that this thus should rarely
396be necessary.
fdoraybacba4a22017-05-10 21:10:00397
Alexander Timine653dfc2020-01-07 17:55:06398### Posting to the Current Thread
399
400*** note
401**IMPORTANT:** To post a task that needs mutual exclusion with the current
Gabriel Charette49e3cd02020-01-28 03:45:27402sequence of tasks but doesn’t absolutely need to run on the current physical
403thread, use `base::SequencedTaskRunnerHandle::Get()` instead of
Alexander Timine653dfc2020-01-07 17:55:06404`base::ThreadTaskRunnerHandle::Get()` (ref. [Posting to the Current
Gabriel Charette49e3cd02020-01-28 03:45:27405Sequence](#Posting-to-the-Current-Virtual_Thread)). That will better document
406the requirements of the posted task and will avoid unnecessarily making your API
407physical thread-affine. In a single-thread task,
408`base::SequencedTaskRunnerHandle::Get()` is equivalent to
409`base::ThreadTaskRunnerHandle::Get()`.
Alexander Timine653dfc2020-01-07 17:55:06410***
411
412If you must post a task to the current physical thread nonetheless, use
413[`base::ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h).
414
415```cpp
416// The task will run on the current thread in the future.
417base::ThreadTaskRunnerHandle::Get()->PostTask(
418 FROM_HERE, base::BindOnce(&Task));
419```
420
fdoraybacba4a22017-05-10 21:10:00421## Posting Tasks to a COM Single-Thread Apartment (STA) Thread (Windows)
422
423Tasks that need to run on a COM Single-Thread Apartment (STA) thread must be
Gabriel Charette39db4c62019-04-29 19:52:38424posted to a `base::SingleThreadTaskRunner` returned by
Gabriel Charette43de5c42020-01-27 22:44:45425`base::ThreadPool::CreateCOMSTATaskRunner()`. As mentioned in [Posting Multiple
426Tasks to the Same Thread](#Posting-Multiple-Tasks-to-the-Same-Thread), all tasks
427posted to the same `base::SingleThreadTaskRunner` run on the same thread in
428posting order.
fdoraybacba4a22017-05-10 21:10:00429
430```cpp
431// Task(A|B|C)UsingCOMSTA will run on the same COM STA thread.
432
433void TaskAUsingCOMSTA() {
434 // [ This runs on a COM STA thread. ]
435
436 // Make COM STA calls.
437 // ...
438
439 // Post another task to the current COM STA thread.
440 base::ThreadTaskRunnerHandle::Get()->PostTask(
441 FROM_HERE, base::BindOnce(&TaskCUsingCOMSTA));
442}
443void TaskBUsingCOMSTA() { }
444void TaskCUsingCOMSTA() { }
445
Gabriel Charette43de5c42020-01-27 22:44:45446auto com_sta_task_runner = base::ThreadPool::CreateCOMSTATaskRunner(...);
fdoraybacba4a22017-05-10 21:10:00447com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskAUsingCOMSTA));
448com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskBUsingCOMSTA));
449```
450
451## Annotating Tasks with TaskTraits
452
Gabriel Charette39db4c62019-04-29 19:52:38453[`base::TaskTraits`](https://cs.chromium.org/chromium/src/base/task/task_traits.h)
Gabriel Charette52fa3ae2019-04-15 21:44:37454encapsulate information about a task that helps the thread pool make better
fdoraybacba4a22017-05-10 21:10:00455scheduling decisions.
456
Gabriel Charette43de5c42020-01-27 22:44:45457Methods that take `base::TaskTraits` can be be passed `{}` when default traits
458are sufficient. Default traits are appropriate for tasks that:
Gabriel Charettede41cad2020-03-03 18:05:06459- Don’t block (ref. MayBlock and WithBaseSyncPrimitives);
460- Pertain to user-blocking activity;
461 (explicitly or implicitly by having an ordering dependency with a component
462 that does)
Gabriel Charette52fa3ae2019-04-15 21:44:37463- Can either block shutdown or be skipped on shutdown (thread pool is free to
464 choose a fitting default).
fdoraybacba4a22017-05-10 21:10:00465Tasks that don’t match this description must be posted with explicit TaskTraits.
466
Gabriel Charette04b138f2018-08-06 00:03:22467[`base/task/task_traits.h`](https://cs.chromium.org/chromium/src/base/task/task_traits.h)
Eric Seckler6cf08db82018-08-30 12:01:55468provides exhaustive documentation of available traits. The content layer also
469provides additional traits in
470[`content/public/browser/browser_task_traits.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_task_traits.h)
471to facilitate posting a task onto a BrowserThread.
472
Gabriel Charette39db4c62019-04-29 19:52:38473Below are some examples of how to specify `base::TaskTraits`.
fdoraybacba4a22017-05-10 21:10:00474
475```cpp
Gabriel Charettede41cad2020-03-03 18:05:06476// This task has no explicit TaskTraits. It cannot block. Its priority is
477// USER_BLOCKING. It will either block shutdown or be skipped on shutdown.
Gabriel Charette43de5c42020-01-27 22:44:45478base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(...));
fdoraybacba4a22017-05-10 21:10:00479
Gabriel Charettede41cad2020-03-03 18:05:06480// This task has the highest priority. The thread pool will schedule it before
481// USER_VISIBLE and BEST_EFFORT tasks.
Gabriel Charette43de5c42020-01-27 22:44:45482base::ThreadPool::PostTask(
fdoraybacba4a22017-05-10 21:10:00483 FROM_HERE, {base::TaskPriority::USER_BLOCKING},
484 base::BindOnce(...));
485
486// This task has the lowest priority and is allowed to block (e.g. it
487// can read a file from disk).
Gabriel Charette43de5c42020-01-27 22:44:45488base::ThreadPool::PostTask(
Gabriel Charetteb10aeebc2018-07-26 20:15:00489 FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()},
fdoraybacba4a22017-05-10 21:10:00490 base::BindOnce(...));
491
492// This task blocks shutdown. The process won't exit before its
493// execution is complete.
Gabriel Charette43de5c42020-01-27 22:44:45494base::ThreadPool::PostTask(
fdoraybacba4a22017-05-10 21:10:00495 FROM_HERE, {base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
496 base::BindOnce(...));
497```
498
499## Keeping the Browser Responsive
500
501Do not perform expensive work on the main thread, the IO thread or any sequence
502that is expected to run tasks with a low latency. Instead, perform expensive
Gabriel Charette43de5c42020-01-27 22:44:45503work asynchronously using `base::ThreadPool::PostTaskAndReply*()` or
Gabriel Charette39db4c62019-04-29 19:52:38504`base::SequencedTaskRunner::PostTaskAndReply()`. Note that
505asynchronous/overlapped I/O on the IO thread are fine.
fdoraybacba4a22017-05-10 21:10:00506
507Example: Running the code below on the main thread will prevent the browser from
508responding to user input for a long time.
509
510```cpp
511// GetHistoryItemsFromDisk() may block for a long time.
512// AddHistoryItemsToOmniboxDropDown() updates the UI and therefore must
513// be called on the main thread.
514AddHistoryItemsToOmniboxDropdown(GetHistoryItemsFromDisk("keyword"));
515```
516
517The code below solves the problem by scheduling a call to
518`GetHistoryItemsFromDisk()` in a thread pool followed by a call to
519`AddHistoryItemsToOmniboxDropdown()` on the origin sequence (the main thread in
520this case). The return value of the first call is automatically provided as
521argument to the second call.
522
523```cpp
Gabriel Charette43de5c42020-01-27 22:44:45524base::ThreadPool::PostTaskAndReplyWithResult(
fdoraybacba4a22017-05-10 21:10:00525 FROM_HERE, {base::MayBlock()},
526 base::BindOnce(&GetHistoryItemsFromDisk, "keyword"),
527 base::BindOnce(&AddHistoryItemsToOmniboxDropdown));
528```
529
530## Posting a Task with a Delay
531
532### Posting a One-Off Task with a Delay
533
534To post a task that must run once after a delay expires, use
Gabriel Charette43de5c42020-01-27 22:44:45535`base::ThreadPool::PostDelayedTask*()` or `base::TaskRunner::PostDelayedTask()`.
fdoraybacba4a22017-05-10 21:10:00536
537```cpp
Gabriel Charette43de5c42020-01-27 22:44:45538base::ThreadPool::PostDelayedTask(
Gabriel Charetteb10aeebc2018-07-26 20:15:00539 FROM_HERE, {base::TaskPriority::BEST_EFFORT}, base::BindOnce(&Task),
fdoraybacba4a22017-05-10 21:10:00540 base::TimeDelta::FromHours(1));
541
542scoped_refptr<base::SequencedTaskRunner> task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45543 base::ThreadPool::CreateSequencedTaskRunner(
544 {base::TaskPriority::BEST_EFFORT});
fdoraybacba4a22017-05-10 21:10:00545task_runner->PostDelayedTask(
546 FROM_HERE, base::BindOnce(&Task), base::TimeDelta::FromHours(1));
547```
548
549*** note
550**NOTE:** A task that has a 1-hour delay probably doesn’t have to run right away
Gabriel Charetteb10aeebc2018-07-26 20:15:00551when its delay expires. Specify `base::TaskPriority::BEST_EFFORT` to prevent it
fdoraybacba4a22017-05-10 21:10:00552from slowing down the browser when its delay expires.
553***
554
555### Posting a Repeating Task with a Delay
556To post a task that must run at regular intervals,
557use [`base::RepeatingTimer`](https://cs.chromium.org/chromium/src/base/timer/timer.h).
558
559```cpp
560class A {
561 public:
562 ~A() {
563 // The timer is stopped automatically when it is deleted.
564 }
565 void StartDoingStuff() {
566 timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1),
567 this, &MyClass::DoStuff);
568 }
569 void StopDoingStuff() {
570 timer_.Stop();
571 }
572 private:
573 void DoStuff() {
574 // This method is called every second on the sequence that invoked
575 // StartDoingStuff().
576 }
577 base::RepeatingTimer timer_;
578};
579```
580
581## Cancelling a Task
582
583### Using base::WeakPtr
584
585[`base::WeakPtr`](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h)
586can be used to ensure that any callback bound to an object is canceled when that
587object is destroyed.
588
589```cpp
590int Compute() { … }
591
592class A {
593 public:
fdoraybacba4a22017-05-10 21:10:00594 void ComputeAndStore() {
595 // Schedule a call to Compute() in a thread pool followed by
596 // a call to A::Store() on the current sequence. The call to
597 // A::Store() is canceled when |weak_ptr_factory_| is destroyed.
598 // (guarantees that |this| will not be used-after-free).
Gabriel Charette43de5c42020-01-27 22:44:45599 base::ThreadPool::PostTaskAndReplyWithResult(
fdoraybacba4a22017-05-10 21:10:00600 FROM_HERE, base::BindOnce(&Compute),
601 base::BindOnce(&A::Store, weak_ptr_factory_.GetWeakPtr()));
602 }
603
604 private:
605 void Store(int value) { value_ = value; }
606
607 int value_;
Jeremy Roman0dd0b2f2019-07-16 21:00:43608 base::WeakPtrFactory<A> weak_ptr_factory_{this};
fdoraybacba4a22017-05-10 21:10:00609};
610```
611
612Note: `WeakPtr` is not thread-safe: `GetWeakPtr()`, `~WeakPtrFactory()`, and
613`Compute()` (bound to a `WeakPtr`) must all run on the same sequence.
614
615### Using base::CancelableTaskTracker
616
617[`base::CancelableTaskTracker`](https://cs.chromium.org/chromium/src/base/task/cancelable_task_tracker.h)
618allows cancellation to happen on a different sequence than the one on which
619tasks run. Keep in mind that `CancelableTaskTracker` cannot cancel tasks that
620have already started to run.
621
622```cpp
Gabriel Charette43de5c42020-01-27 22:44:45623auto task_runner = base::ThreadPool::CreateTaskRunner({});
fdoraybacba4a22017-05-10 21:10:00624base::CancelableTaskTracker cancelable_task_tracker;
625cancelable_task_tracker.PostTask(task_runner.get(), FROM_HERE,
Peter Kasting341e1fb2018-02-24 00:03:01626 base::DoNothing());
fdoraybacba4a22017-05-10 21:10:00627// Cancels Task(), only if it hasn't already started running.
628cancelable_task_tracker.TryCancelAll();
629```
630
Etienne Pierre-dorayd3882992020-01-14 20:34:11631## Posting a Job to run in parallel
632
633The [`base::PostJob`](https://cs.chromium.org/chromium/src/base/task/post_job.h)
634is a power user API to be able to schedule a single base::RepeatingCallback
635worker task and request that ThreadPool workers invoke it concurrently.
636This avoids degenerate cases:
637* Calling `PostTask()` for each work item, causing significant overhead.
638* Fixed number of `PostTask()` calls that split the work and might run for a
639 long time. This is problematic when many components post “num cores” tasks and
640 all expect to use all the cores. In these cases, the scheduler lacks context
641 to be fair to multiple same-priority requests and/or ability to request lower
642 priority work to yield when high priority work comes in.
643
Etienne Pierre-doray6d3cd9192020-04-06 21:10:37644See [`base/task/job_perftest.cc`](https://cs.chromium.org/chromium/src/base/task/job_perftest.cc)
645for a complete example.
646
Etienne Pierre-dorayd3882992020-01-14 20:34:11647```cpp
648// A canonical implementation of |worker_task|.
649void WorkerTask(base::JobDelegate* job_delegate) {
650 while (!job_delegate->ShouldYield()) {
651 auto work_item = TakeWorkItem(); // Smallest unit of work.
652 if (!work_item)
653 return:
654 ProcessWork(work_item);
655 }
656}
657
658// Returns the latest thread-safe number of incomplete work items.
Etienne Pierre-Dorayf91d7a02020-09-11 15:53:27659void NumIncompleteWorkItems(size_t worker_count) {
660 // NumIncompleteWorkItems() may use |worker_count| if it needs to account for
661 // local work lists, which is easier than doing its own accounting, keeping in
662 // mind that the actual number of items may be racily overestimated and thus
663 // WorkerTask() may be called when there's no available work.
664 return GlobalQueueSize() + worker_count;
665}
Etienne Pierre-dorayd3882992020-01-14 20:34:11666
Gabriel Charette1138d602020-01-29 08:51:52667base::PostJob(FROM_HERE, {},
Etienne Pierre-dorayd3882992020-01-14 20:34:11668 base::BindRepeating(&WorkerTask),
669 base::BindRepeating(&NumIncompleteWorkItems));
670```
671
672By doing as much work as possible in a loop when invoked, the worker task avoids
673scheduling overhead. Meanwhile `base::JobDelegate::ShouldYield()` is
674periodically invoked to conditionally exit and let the scheduler prioritize
675other work. This yield-semantic allows, for example, a user-visible job to use
676all cores but get out of the way when a user-blocking task comes in.
677
678### Adding additional work to a running job.
679
680When new work items are added and the API user wants additional threads to
681invoke the worker task concurrently,
682`JobHandle/JobDelegate::NotifyConcurrencyIncrease()` *must* be invoked shortly
683after max concurrency increases.
684
fdoraybacba4a22017-05-10 21:10:00685## Testing
686
Gabriel Charette0b20ee6c2019-09-18 14:06:12687For more details see [Testing Components Which Post
688Tasks](threading_and_tasks_testing.md).
689
fdoraybacba4a22017-05-10 21:10:00690To test code that uses `base::ThreadTaskRunnerHandle`,
691`base::SequencedTaskRunnerHandle` or a function in
Gabriel Charette39db4c62019-04-29 19:52:38692[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h),
693instantiate a
Gabriel Charette0b20ee6c2019-09-18 14:06:12694[`base::test::TaskEnvironment`](https://cs.chromium.org/chromium/src/base/test/task_environment.h)
Gabriel Charette39db4c62019-04-29 19:52:38695for the scope of the test. If you need BrowserThreads, use
Gabriel Charette798fde72019-08-20 22:24:04696`content::BrowserTaskEnvironment` instead of
Gabriel Charette694c3c332019-08-19 14:53:05697`base::test::TaskEnvironment`.
fdoraybacba4a22017-05-10 21:10:00698
Gabriel Charette694c3c332019-08-19 14:53:05699Tests can run the `base::test::TaskEnvironment`'s message pump using a
Gabriel Charette39db4c62019-04-29 19:52:38700`base::RunLoop`, which can be made to run until `Quit()` (explicitly or via
701`RunLoop::QuitClosure()`), or to `RunUntilIdle()` ready-to-run tasks and
702immediately return.
Wezd9e4cb772019-01-09 03:07:03703
Wez9d5dd282020-02-10 17:21:22704TaskEnvironment configures RunLoop::Run() to GTEST_FAIL() if it hasn't been
Wezd9e4cb772019-01-09 03:07:03705explicitly quit after TestTimeouts::action_timeout(). This is preferable to
706having the test hang if the code under test fails to trigger the RunLoop to
Wez9d5dd282020-02-10 17:21:22707quit. The timeout can be overridden with base::test::ScopedRunLoopTimeout.
Wezd9e4cb772019-01-09 03:07:03708
fdoraybacba4a22017-05-10 21:10:00709```cpp
710class MyTest : public testing::Test {
711 public:
712 // ...
713 protected:
Gabriel Charette694c3c332019-08-19 14:53:05714 base::test::TaskEnvironment task_environment_;
fdoraybacba4a22017-05-10 21:10:00715};
716
717TEST(MyTest, MyTest) {
718 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&A));
719 base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
720 base::BindOnce(&B));
721 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
722 FROM_HERE, base::BindOnce(&C), base::TimeDelta::Max());
723
724 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until it is empty.
725 // Delayed tasks are not added to the queue until they are ripe for execution.
726 base::RunLoop().RunUntilIdle();
727 // A and B have been executed. C is not ripe for execution yet.
728
729 base::RunLoop run_loop;
730 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&D));
731 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
732 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&E));
733
734 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until QuitClosure is
735 // invoked.
736 run_loop.Run();
737 // D and run_loop.QuitClosure() have been executed. E is still in the queue.
738
Gabriel Charette52fa3ae2019-04-15 21:44:37739 // Tasks posted to thread pool run asynchronously as they are posted.
Gabriel Charette43de5c42020-01-27 22:44:45740 base::ThreadPool::PostTask(FROM_HERE, {}, base::BindOnce(&F));
fdoraybacba4a22017-05-10 21:10:00741 auto task_runner =
Gabriel Charette43de5c42020-01-27 22:44:45742 base::ThreadPool::CreateSequencedTaskRunner({});
fdoraybacba4a22017-05-10 21:10:00743 task_runner->PostTask(FROM_HERE, base::BindOnce(&G));
744
Gabriel Charette52fa3ae2019-04-15 21:44:37745 // To block until all tasks posted to thread pool are done running:
Gabriel Charette43fd3702019-05-29 16:36:51746 base::ThreadPoolInstance::Get()->FlushForTesting();
fdoraybacba4a22017-05-10 21:10:00747 // F and G have been executed.
748
Gabriel Charette43de5c42020-01-27 22:44:45749 base::ThreadPool::PostTaskAndReplyWithResult(
750 FROM_HERE, {}, base::BindOnce(&H), base::BindOnce(&I));
fdoraybacba4a22017-05-10 21:10:00751
752 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until both the
753 // (Thread|Sequenced)TaskRunnerHandle queue and the TaskSchedule queue are
754 // empty:
Gabriel Charette694c3c332019-08-19 14:53:05755 task_environment_.RunUntilIdle();
fdoraybacba4a22017-05-10 21:10:00756 // E, H, I have been executed.
757}
758```
759
Gabriel Charette52fa3ae2019-04-15 21:44:37760## Using ThreadPool in a New Process
fdoraybacba4a22017-05-10 21:10:00761
Gabriel Charette43fd3702019-05-29 16:36:51762ThreadPoolInstance needs to be initialized in a process before the functions in
Gabriel Charette04b138f2018-08-06 00:03:22763[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h)
Gabriel Charette43fd3702019-05-29 16:36:51764can be used. Initialization of ThreadPoolInstance in the Chrome browser process
765and child processes (renderer, GPU, utility) has already been taken care of. To
766use ThreadPoolInstance in another process, initialize ThreadPoolInstance early
767in the main function:
fdoraybacba4a22017-05-10 21:10:00768
769```cpp
Gabriel Charette43fd3702019-05-29 16:36:51770// This initializes and starts ThreadPoolInstance with default params.
771base::ThreadPoolInstance::CreateAndStartWithDefaultParams(“process_name”);
772// The base/task/post_task.h API can now be used with base::ThreadPool trait.
773// Tasks will be // scheduled as they are posted.
fdoraybacba4a22017-05-10 21:10:00774
Gabriel Charette43fd3702019-05-29 16:36:51775// This initializes ThreadPoolInstance.
776base::ThreadPoolInstance::Create(“process_name”);
777// The base/task/post_task.h API can now be used with base::ThreadPool trait. No
778// threads will be created and no tasks will be scheduled until after Start() is
779// called.
780base::ThreadPoolInstance::Get()->Start(params);
Gabriel Charette52fa3ae2019-04-15 21:44:37781// ThreadPool can now create threads and schedule tasks.
fdoraybacba4a22017-05-10 21:10:00782```
783
Gabriel Charette43fd3702019-05-29 16:36:51784And shutdown ThreadPoolInstance late in the main function:
fdoraybacba4a22017-05-10 21:10:00785
786```cpp
Gabriel Charette43fd3702019-05-29 16:36:51787base::ThreadPoolInstance::Get()->Shutdown();
fdoraybacba4a22017-05-10 21:10:00788// Tasks posted with TaskShutdownBehavior::BLOCK_SHUTDOWN and
789// tasks posted with TaskShutdownBehavior::SKIP_ON_SHUTDOWN that
790// have started to run before the Shutdown() call have now completed their
791// execution. Tasks posted with
792// TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN may still be
793// running.
794```
Gabriel Charetteb86e5fe62017-06-08 19:39:28795## TaskRunner ownership (encourage no dependency injection)
Sebastien Marchandc95489b2017-05-25 16:39:34796
797TaskRunners shouldn't be passed through several components. Instead, the
798components that uses a TaskRunner should be the one that creates it.
799
800See [this example](https://codereview.chromium.org/2885173002/) of a
801refactoring where a TaskRunner was passed through a lot of components only to be
802used in an eventual leaf. The leaf can and should now obtain its TaskRunner
803directly from
Gabriel Charette04b138f2018-08-06 00:03:22804[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h).
Gabriel Charetteb86e5fe62017-06-08 19:39:28805
Gabriel Charette694c3c332019-08-19 14:53:05806As mentioned above, `base::test::TaskEnvironment` allows unit tests to
Gabriel Charette39db4c62019-04-29 19:52:38807control tasks posted from underlying TaskRunners. In rare cases where a test
808needs to more precisely control task ordering: dependency injection of
809TaskRunners can be useful. For such cases the preferred approach is the
810following:
Gabriel Charetteb86e5fe62017-06-08 19:39:28811
812```cpp
Gabriel Charette39db4c62019-04-29 19:52:38813class Foo {
Gabriel Charetteb86e5fe62017-06-08 19:39:28814 public:
815
Gabriel Charette39db4c62019-04-29 19:52:38816 // Overrides |background_task_runner_| in tests.
Gabriel Charetteb86e5fe62017-06-08 19:39:28817 void SetBackgroundTaskRunnerForTesting(
Gabriel Charette39db4c62019-04-29 19:52:38818 scoped_refptr<base::SequencedTaskRunner> background_task_runner) {
819 background_task_runner_ = std::move(background_task_runner);
820 }
Gabriel Charetteb86e5fe62017-06-08 19:39:28821
822 private:
michaelpg12c04572017-06-26 23:25:06823 scoped_refptr<base::SequencedTaskRunner> background_task_runner_ =
Gabriel Charette43de5c42020-01-27 22:44:45824 base::ThreadPool::CreateSequencedTaskRunner(
Gabriel Charetteb10aeebc2018-07-26 20:15:00825 {base::MayBlock(), base::TaskPriority::BEST_EFFORT});
Gabriel Charetteb86e5fe62017-06-08 19:39:28826}
827```
828
829Note that this still allows removing all layers of plumbing between //chrome and
830that component since unit tests will use the leaf layer directly.
Gabriel Charette8917f4c2018-11-22 15:50:28831
832## FAQ
833See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more examples.
Gabriel Charette43de5c42020-01-27 22:44:45834
835[task APIs v3]: https://docs.google.com/document/d/1tssusPykvx3g0gvbvU4HxGyn3MjJlIylnsH13-Tv6s4/edit?ts=5de99a52#heading=h.ss4tw38hvh3s
Carlos Caballero40b6d042020-06-16 06:50:25836
837## Internals
838
839### SequenceManager
840
841[SequenceManager](https://cs.chromium.org/chromium/src/base/task/sequence_manager/sequence_manager.h)
842manages TaskQueues which have different properties (e.g. priority, common task
843type) multiplexing all posted tasks into a single backing sequence. This will
844usually be a MessagePump. Depending on the type of message pump used other
845events such as UI messages may be processed as well. On Windows APC calls (as
846time permits) and signals sent to a registered set of HANDLEs may also be
847processed.
848
Carlos Caballero4a050922020-07-02 11:43:38849### MessagePump
Carlos Caballero40b6d042020-06-16 06:50:25850
851[MessagePumps](https://cs.chromium.org/chromium/src/base/message_loop/message_pump.h)
852are responsible for processing native messages as well as for giving cycles to
853their delegate (SequenceManager) periodically. MessagePumps take care to mixing
854delegate callbacks with native message processing so neither type of event
855starves the other of cycles.
856
857There are different [MessagePumpTypes](https://cs.chromium.org/chromium/src/base/message_loop/message_pump_type.h),
858most common are:
859
860* DEFAULT: Supports tasks and timers only
861
862* UI: Supports native UI events (e.g. Windows messages)
863
864* IO: Supports asynchronous IO (not file I/O!)
865
866* CUSTOM: User provided implementation of MessagePump interface
867
Carlos Caballero4a050922020-07-02 11:43:38868### RunLoop
Carlos Caballero40b6d042020-06-16 06:50:25869
870RunLoop is s helper class to run the RunLoop::Delegate associated with the
871current thread (usually a SequenceManager). Create a RunLoop on the stack and
872call Run/Quit to run a nested RunLoop but please avoid nested loops in
873production code!
874
Carlos Caballero4a050922020-07-02 11:43:38875### Task Reentrancy
Carlos Caballero40b6d042020-06-16 06:50:25876
877SequenceManager has task reentrancy protection. This means that if a
878task is being processed, a second task cannot start until the first task is
879finished. Reentrancy can happen when processing a task, and an inner
880message pump is created. That inner pump then processes native messages
881which could implicitly start an inner task. Inner message pumps are created
882with dialogs (DialogBox), common dialogs (GetOpenFileName), OLE functions
883(DoDragDrop), printer functions (StartDoc) and *many* others.
884
885```cpp
886Sample workaround when inner task processing is needed:
887 HRESULT hr;
888 {
Carlos Caballerob25fe8472020-07-17 10:27:17889 CurrentThread::ScopedNestableTaskAllower allow;
Carlos Caballero40b6d042020-06-16 06:50:25890 hr = DoDragDrop(...); // Implicitly runs a modal message loop.
891 }
892 // Process |hr| (the result returned by DoDragDrop()).
893```
894
895Please be SURE your task is reentrant (nestable) and all global variables
896are stable and accessible before before using
Carlos Caballerob25fe8472020-07-17 10:27:17897CurrentThread::ScopedNestableTaskAllower.
Carlos Caballero40b6d042020-06-16 06:50:25898
899## APIs for general use
900
901User code should hardly ever need to access SequenceManager APIs directly as
902these are meant for code that deals with scheduling. Instead you should use the
903following:
904
905* base::RunLoop: Drive the SequenceManager from the thread it's bound to.
906
907* base::Thread/SequencedTaskRunnerHandle: Post back to the SequenceManager TaskQueues from a task running on it.
908
909* SequenceLocalStorageSlot : Bind external state to a sequence.
910
Carlos Caballero4a050922020-07-02 11:43:38911* base::CurrentThread : Proxy to a subset of Task related APIs bound to the current thread
Carlos Caballero40b6d042020-06-16 06:50:25912
913* Embedders may provide their own static accessors to post tasks on specific loops (e.g. content::BrowserThreads).
914
915### SingleThreadTaskExecutor and TaskEnvironment
916
917Instead of having to deal with SequenceManager and TaskQueues code that needs a
918simple task posting environment (one default task queue) can use a
919[SingleThreadTaskExecutor](https://cs.chromium.org/chromium/src/base/task/single_thread_task_executor.h).
920
921Unit tests can use [TaskEnvironment](https://cs.chromium.org/chromium/src/base/test/task_environment.h)
922which is highly configurable.
Carlos Caballero4a050922020-07-02 11:43:38923
Carlos Caballerob25fe8472020-07-17 10:27:17924## MessageLoop and CurrentThread
Carlos Caballero4a050922020-07-02 11:43:38925
Carlos Caballerob25fe8472020-07-17 10:27:17926You might come across references to MessageLoop or CurrentThread in the
Carlos Caballero4a050922020-07-02 11:43:38927code or documentation. These classes no longer exist and we are in the process
Carlos Caballerob25fe8472020-07-17 10:27:17928or getting rid of all references to them. base::CurrentThread was replaced
Carlos Caballero4a050922020-07-02 11:43:38929by base::CurrentThread and the drop in replacements for base::MessageLoop are
930base::SingleThreadTaskExecutor and base::Test::TaskEnvironment.