1# Threading and Tasks in Chrome 2 3[TOC] 4 5Note: See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more 6examples. 7 8## Overview 9 10Chrome 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)). 25 26### Nomenclature 27 28## Core Concepts 29 * **Task**: A unit of work to be processed. Effectively a function pointer with 30 optionally associated state. In Chrome this is `base::Callback` created via 31 `base::Bind` 32 ([documentation](https://chromium.googlesource.com/chromium/src/+/HEAD/docs/callback.md)). 33 * **Task queue**: A queue of tasks to be processed. 34 * **Physical thread**: An operating system provided thread (e.g. pthread on 35 POSIX or CreateThread() on Windows). The Chrome cross-platform abstraction 36 is `base::PlatformThread`. You should pretty much never use this directly. 37 * **`base::Thread`**: A physical thread forever processing messages from a 38 dedicated task queue until Quit(). You should pretty much never be creating 39 your own `base::Thread`'s. 40 * **Thread pool**: A pool of physical threads with a shared task queue. In 41 Chrome, this is `base::ThreadPoolInstance`. There's exactly one instance per 42 Chrome process, it serves tasks posted through 43 [`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h) 44 and as such you should rarely need to use the `base::ThreadPoolInstance` API 45 directly (more on posting tasks later). 46 * **Sequence** or **Virtual thread**: A chrome-managed thread of execution. 47 Like a physical thread, only one task can run on a given sequence / virtual 48 thread at any given moment and each task sees the side-effects of the 49 preceding tasks. Tasks are executed sequentially but may hop physical 50 threads between each one. 51 * **Task runner**: An interface through which tasks can be posted. In Chrome 52 this is `base::TaskRunner`. 53 * **Sequenced task runner**: A task runner which guarantees that tasks posted 54 to it will run sequentially, in posted order. Each such task is guaranteed to 55 see the side-effects of the task preceding it. Tasks posted to a sequenced 56 task runner are typically processed by a single thread (virtual or physical). 57 In Chrome this is `base::SequencedTaskRunner` which is-a 58 `base::TaskRunner`. 59 * **Single-thread task runner**: A sequenced task runner which guarantees that 60 all tasks will be processed by the same physical thread. In Chrome this is 61 `base::SingleThreadTaskRunner` which is-a `base::SequencedTaskRunner`. We 62 [prefer sequences to threads](#prefer-sequences-to-physical-threads) whenever 63 possible. 64 65## Threading Lexicon 66Note to the reader: the following terms are an attempt to bridge the gap between 67common threading nomenclature and the way we use them in Chrome. It might be a 68bit heavy if you're just getting started. Should this be hard to parse, consider 69skipping to the more detailed sections below and referring back to this as 70necessary. 71 72 * **Thread-unsafe**: The vast majority of types in Chrome are thread-unsafe 73 (by design). Access to such types/methods must be externally synchronized. 74 Typically thread-unsafe types require that all tasks accessing their state be 75 posted to the same `base::SequencedTaskRunner` and they verify this in debug 76 builds with a `SEQUENCE_CHECKER` member. Locks are also an option to 77 synchronize access but in Chrome we strongly 78 [prefer sequences to locks](#Using-Sequences-Instead-of-Locks). 79 * **Thread-affine**: Such types/methods need to be always accessed from the 80 same physical thread (i.e. from the same `base::SingleThreadTaskRunner`) and 81 typically have a `THREAD_CHECKER` member to verify that they are. Short of 82 using a third-party API or having a leaf dependency which is thread-affine: 83 there's pretty much no reason for a type to be thread-affine in Chrome. 84 Note that `base::SingleThreadTaskRunner` is-a `base::SequencedTaskRunner` so 85 thread-affine is a subset of thread-unsafe. Thread-affine is also sometimes 86 referred to as **thread-hostile**. 87 * **Thread-safe**: Such types/methods can be safely accessed concurrently. 88 * **Thread-compatible**: Such types provide safe concurrent access to const 89 methods but require synchronization for non-const (or mixed const/non-const 90 access). Chrome doesn't expose reader-writer locks; as such, the only use 91 case for this is objects (typically globals) which are initialized once in a 92 thread-safe manner (either in the single-threaded phase of startup or lazily 93 through a thread-safe static-local-initialization paradigm a la 94 `base::NoDestructor`) and forever after immutable. 95 * **Immutable**: A subset of thread-compatible types which cannot be modified 96 after construction. 97 * **Sequence-friendly**: Such types/methods are thread-unsafe types which 98 support being invoked from a `base::SequencedTaskRunner`. Ideally this would 99 be the case for all thread-unsafe types but legacy code sometimes has 100 overzealous checks that enforce thread-affinity in mere thread-unsafe 101 scenarios. See [Prefer Sequences to 102 Threads](#prefer-sequences-to-physical-threads) below for more details. 103 104### Threads 105 106Every Chrome process has 107 108* a main thread 109 * in the browser process (BrowserThread::UI): updates the UI 110 * in renderer processes (Blink main thread): runs most of Blink 111* an IO thread 112 * in the browser process (BrowserThread::IO): handles IPCs and network 113 requests 114 * in renderer processes: handles IPCs 115* a few more special-purpose threads 116* and a pool of general-purpose threads 117 118Most threads have a loop that gets tasks from a queue and runs them (the queue 119may be shared between multiple threads). 120 121### Tasks 122 123A task is a `base::OnceClosure` added to a queue for asynchronous execution. 124 125A `base::OnceClosure` stores a function pointer and arguments. It has a `Run()` 126method that invokes the function pointer using the bound arguments. It is 127created using `base::BindOnce`. (ref. [Callback<> and Bind() 128documentation](callback.md)). 129 130``` 131void TaskA() {} 132void TaskB(int v) {} 133 134auto task_a = base::BindOnce(&TaskA); 135auto task_b = base::BindOnce(&TaskB, 42); 136``` 137 138A group of tasks can be executed in one of the following ways: 139 140* [Parallel](#Posting-a-Parallel-Task): No task execution ordering, possibly all 141 at once on any thread 142* [Sequenced](#Posting-a-Sequenced-Task): Tasks executed in posting order, one 143 at a time on any thread. 144* [Single Threaded](#Posting-Multiple-Tasks-to-the-Same-Thread): Tasks executed 145 in posting order, one at a time on a single thread. 146 * [COM Single Threaded](#Posting-Tasks-to-a-COM-Single_Thread-Apartment-STA_Thread-Windows): 147 A variant of single threaded with COM initialized. 148 149### Prefer Sequences to Physical Threads 150 151Sequenced execution (on virtual threads) is strongly preferred to 152single-threaded execution (on physical threads). Except for types/methods bound 153to the main thread (UI) or IO threads: thread-safety is better achieved via 154`base::SequencedTaskRunner` than through managing your own physical threads 155(ref. [Posting a Sequenced Task](#posting-a-sequenced-task) below). 156 157All APIs which are exposed for "current physical thread" have an equivalent for 158"current sequence" 159([mapping](threading_and_tasks_faq.md#How-to-migrate-from-SingleThreadTaskRunner-to-SequencedTaskRunner)). 160 161If you find yourself writing a sequence-friendly type and it fails 162thread-affinity checks (e.g., `THREAD_CHECKER`) in a leaf dependency: consider 163making that dependency sequence-friendly as well. Most core APIs in Chrome are 164sequence-friendly, but some legacy types may still over-zealously use 165ThreadChecker/ThreadTaskRunnerHandle/SingleThreadTaskRunner when they could 166instead rely on the "current sequence" and no longer be thread-affine. 167 168## Posting a Parallel Task 169 170### Direct Posting to the Thread Pool 171 172A task that can run on any thread and doesn’t have ordering or mutual exclusion 173requirements with other tasks should be posted using one of the 174`base::ThreadPool::PostTask*()` functions defined in 175[`base/task/thread_pool.h`](https://cs.chromium.org/chromium/src/base/task/thread_pool.h). 176 177```cpp 178base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(&Task)); 179``` 180 181This posts tasks with default traits. 182 183The `base::ThreadPool::PostTask*()` functions allow the caller to provide 184additional details about the task via TaskTraits (ref. [Annotating Tasks with 185TaskTraits](#Annotating-Tasks-with-TaskTraits)). 186 187```cpp 188base::ThreadPool::PostTask( 189 FROM_HERE, {base::TaskPriority::BEST_EFFORT, MayBlock()}, 190 base::BindOnce(&Task)); 191``` 192 193### Posting via a TaskRunner 194 195A parallel 196[`base::TaskRunner`](https://cs.chromium.org/chromium/src/base/task_runner.h) is 197an alternative to calling `base::ThreadPool::PostTask*()` directly. This is 198mainly useful when it isn’t known in advance whether tasks will be posted in 199parallel, in sequence, or to a single-thread (ref. [Posting a Sequenced 200Task](#Posting-a-Sequenced-Task), [Posting Multiple Tasks to the Same 201Thread](#Posting-Multiple-Tasks-to-the-Same-Thread)). Since `base::TaskRunner` 202is the base class of `base::SequencedTaskRunner` and 203`base::SingleThreadTaskRunner`, a `scoped_refptr<TaskRunner>` member can hold a 204`base::TaskRunner`, a `base::SequencedTaskRunner` or a 205`base::SingleThreadTaskRunner`. 206 207```cpp 208class A { 209 public: 210 A() = default; 211 212 void PostSomething() { 213 task_runner_->PostTask(FROM_HERE, base::BindOnce(&A, &DoSomething)); 214 } 215 216 void DoSomething() { 217 } 218 219 private: 220 scoped_refptr<base::TaskRunner> task_runner_ = 221 base::ThreadPool::CreateTaskRunner({base::TaskPriority::USER_VISIBLE}); 222}; 223``` 224 225Unless a test needs to control precisely how tasks are executed, it is preferred 226to call `base::ThreadPool::PostTask*()` directly (ref. [Testing](#Testing) for 227less invasive ways of controlling tasks in tests). 228 229## Posting a Sequenced Task 230 231A sequence is a set of tasks that run one at a time in posting order (not 232necessarily on the same thread). To post tasks as part of a sequence, use a 233[`base::SequencedTaskRunner`](https://cs.chromium.org/chromium/src/base/sequenced_task_runner.h). 234 235### Posting to a New Sequence 236 237A `base::SequencedTaskRunner` can be created by 238`base::ThreadPool::CreateSequencedTaskRunner()`. 239 240```cpp 241scoped_refptr<SequencedTaskRunner> sequenced_task_runner = 242 base::ThreadPool::CreateSequencedTaskRunner(...); 243 244// TaskB runs after TaskA completes. 245sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA)); 246sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB)); 247``` 248 249### Posting to the Current (Virtual) Thread 250 251The preferred way of posting to the current (virtual) thread is via 252`base::SequencedTaskRunnerHandle::Get()`. 253 254```cpp 255// The task will run on the current (virtual) thread's default task queue. 256base::SequencedTaskRunnerHandle::Get()->PostTask( 257 FROM_HERE, base::BindOnce(&Task); 258``` 259 260Note that SequencedTaskRunnerHandle::Get() returns the default queue for the 261current virtual thread. On threads with multiple task queues (e.g. 262BrowserThread::UI) this can be a different queue than the one the current task 263belongs to. The "current" task runner is intentionally not exposed via a static 264getter. Either you know it already and can post to it directly or you don't and 265the only sensible destination is the default queue. 266 267## Using Sequences Instead of Locks 268 269Usage of locks is discouraged in Chrome. Sequences inherently provide 270thread-safety. Prefer classes that are always accessed from the same 271sequence to managing your own thread-safety with locks. 272 273**Thread-safe but not thread-affine; how so?** Tasks posted to the same sequence 274will run in sequential order. After a sequenced task completes, the next task 275may be picked up by a different worker thread, but that task is guaranteed to 276see any side-effects caused by the previous one(s) on its sequence. 277 278```cpp 279class A { 280 public: 281 A() { 282 // Do not require accesses to be on the creation sequence. 283 DETACH_FROM_SEQUENCE(sequence_checker_); 284 } 285 286 void AddValue(int v) { 287 // Check that all accesses are on the same sequence. 288 DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); 289 values_.push_back(v); 290} 291 292 private: 293 SEQUENCE_CHECKER(sequence_checker_); 294 295 // No lock required, because all accesses are on the 296 // same sequence. 297 std::vector<int> values_; 298}; 299 300A a; 301scoped_refptr<SequencedTaskRunner> task_runner_for_a = ...; 302task_runner_for_a->PostTask(FROM_HERE, 303 base::BindOnce(&A::AddValue, base::Unretained(&a), 42)); 304task_runner_for_a->PostTask(FROM_HERE, 305 base::BindOnce(&A::AddValue, base::Unretained(&a), 27)); 306 307// Access from a different sequence causes a DCHECK failure. 308scoped_refptr<SequencedTaskRunner> other_task_runner = ...; 309other_task_runner->PostTask(FROM_HERE, 310 base::BindOnce(&A::AddValue, base::Unretained(&a), 1)); 311``` 312 313Locks should only be used to swap in a shared data structure that can be 314accessed on multiple threads. If one thread updates it based on expensive 315computation or through disk access, then that slow work should be done without 316holding the lock. Only when the result is available should the lock be used to 317swap in the new data. An example of this is in PluginList::LoadPlugins 318([`content/browser/plugin_list.cc`](https://cs.chromium.org/chromium/src/content/browser/plugin_list.cc). 319If you must use locks, 320[here](https://www.chromium.org/developers/lock-and-condition-variable) are some 321best practices and pitfalls to avoid. 322 323In order to write non-blocking code, many APIs in Chrome are asynchronous. 324Usually this means that they either need to be executed on a particular 325thread/sequence and will return results via a custom delegate interface, or they 326take a `base::Callback<>` object that is called when the requested operation is 327completed. Executing work on a specific thread/sequence is covered in the 328PostTask sections above. 329 330## Posting Multiple Tasks to the Same Thread 331 332If multiple tasks need to run on the same thread, post them to a 333[`base::SingleThreadTaskRunner`](https://cs.chromium.org/chromium/src/base/single_thread_task_runner.h). 334All tasks posted to the same `base::SingleThreadTaskRunner` run on the same thread in 335posting order. 336 337### Posting to the Main Thread or to the IO Thread in the Browser Process 338 339To post tasks to the main thread or to the IO thread, use 340`content::GetUIThreadTaskRunner({})` or `content::GetIOThreadTaskRunner({})` 341from 342[`content/public/browser/browser_thread.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_thread.h) 343 344You may provide additional BrowserTaskTraits as a parameter to those methods 345though this is generally still uncommon in BrowserThreads and should be reserved 346for advanced use cases. 347 348There's an ongoing migration ([task APIs v3]) away from the previous 349base-API-with-traits which you may still find throughout the codebase (it's 350equivalent): 351 352```cpp 353base::PostTask(FROM_HERE, {content::BrowserThread::UI}, ...); 354 355base::CreateSingleThreadTaskRunner({content::BrowserThread::IO}) 356 ->PostTask(FROM_HERE, ...); 357``` 358 359Note: For the duration of the migration, you'll unfortunately need to continue 360manually including 361[`content/public/browser/browser_task_traits.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_task_traits.h). 362to use the browser_thread.h API. 363 364The main thread and the IO thread are already super busy. Therefore, prefer 365posting to a general purpose thread when possible (ref. 366[Posting a Parallel Task](#Posting-a-Parallel-Task), 367[Posting a Sequenced task](#Posting-a-Sequenced-Task)). 368Good reasons to post to the main thread are to update the UI or access objects 369that are bound to it (e.g. `Profile`). A good reason to post to the IO thread is 370to access the internals of components that are bound to it (e.g. IPCs, network). 371Note: It is not necessary to have an explicit post task to the IO thread to 372send/receive an IPC or send/receive data on the network. 373 374### Posting to the Main Thread in a Renderer Process 375TODO(blink-dev) 376 377### Posting to a Custom SingleThreadTaskRunner 378 379If multiple tasks need to run on the same thread and that thread doesn’t have to 380be the main thread or the IO thread, post them to a 381`base::SingleThreadTaskRunner` created by 382`base::Threadpool::CreateSingleThreadTaskRunner`. 383 384```cpp 385scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner = 386 base::Threadpool::CreateSingleThreadTaskRunner(...); 387 388// TaskB runs after TaskA completes. Both tasks run on the same thread. 389single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA)); 390single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB)); 391``` 392 393Remember that we [prefer sequences to physical 394threads](#prefer-sequences-to-physical-threads) and that this thus should rarely 395be necessary. 396 397### Posting to the Current Thread 398 399*** note 400**IMPORTANT:** To post a task that needs mutual exclusion with the current 401sequence of tasks but doesn’t absolutely need to run on the current physical 402thread, use `base::SequencedTaskRunnerHandle::Get()` instead of 403`base::ThreadTaskRunnerHandle::Get()` (ref. [Posting to the Current 404Sequence](#Posting-to-the-Current-Virtual_Thread)). That will better document 405the requirements of the posted task and will avoid unnecessarily making your API 406physical thread-affine. In a single-thread task, 407`base::SequencedTaskRunnerHandle::Get()` is equivalent to 408`base::ThreadTaskRunnerHandle::Get()`. 409*** 410 411If you must post a task to the current physical thread nonetheless, use 412[`base::ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h). 413 414```cpp 415// The task will run on the current thread in the future. 416base::ThreadTaskRunnerHandle::Get()->PostTask( 417 FROM_HERE, base::BindOnce(&Task)); 418``` 419 420## Posting Tasks to a COM Single-Thread Apartment (STA) Thread (Windows) 421 422Tasks that need to run on a COM Single-Thread Apartment (STA) thread must be 423posted to a `base::SingleThreadTaskRunner` returned by 424`base::ThreadPool::CreateCOMSTATaskRunner()`. As mentioned in [Posting Multiple 425Tasks to the Same Thread](#Posting-Multiple-Tasks-to-the-Same-Thread), all tasks 426posted to the same `base::SingleThreadTaskRunner` run on the same thread in 427posting order. 428 429```cpp 430// Task(A|B|C)UsingCOMSTA will run on the same COM STA thread. 431 432void TaskAUsingCOMSTA() { 433 // [ This runs on a COM STA thread. ] 434 435 // Make COM STA calls. 436 // ... 437 438 // Post another task to the current COM STA thread. 439 base::ThreadTaskRunnerHandle::Get()->PostTask( 440 FROM_HERE, base::BindOnce(&TaskCUsingCOMSTA)); 441} 442void TaskBUsingCOMSTA() { } 443void TaskCUsingCOMSTA() { } 444 445auto com_sta_task_runner = base::ThreadPool::CreateCOMSTATaskRunner(...); 446com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskAUsingCOMSTA)); 447com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskBUsingCOMSTA)); 448``` 449 450## Annotating Tasks with TaskTraits 451 452[`base::TaskTraits`](https://cs.chromium.org/chromium/src/base/task/task_traits.h) 453encapsulate information about a task that helps the thread pool make better 454scheduling decisions. 455 456Methods that take `base::TaskTraits` can be be passed `{}` when default traits 457are sufficient. Default traits are appropriate for tasks that: 458- Don’t block (ref. MayBlock and WithBaseSyncPrimitives); 459- Pertain to user-blocking activity; 460 (explicitly or implicitly by having an ordering dependency with a component 461 that does) 462- Can either block shutdown or be skipped on shutdown (thread pool is free to 463 choose a fitting default). 464Tasks that don’t match this description must be posted with explicit TaskTraits. 465 466[`base/task/task_traits.h`](https://cs.chromium.org/chromium/src/base/task/task_traits.h) 467provides exhaustive documentation of available traits. The content layer also 468provides additional traits in 469[`content/public/browser/browser_task_traits.h`](https://cs.chromium.org/chromium/src/content/public/browser/browser_task_traits.h) 470to facilitate posting a task onto a BrowserThread. 471 472Below are some examples of how to specify `base::TaskTraits`. 473 474```cpp 475// This task has no explicit TaskTraits. It cannot block. Its priority is 476// USER_BLOCKING. It will either block shutdown or be skipped on shutdown. 477base::ThreadPool::PostTask(FROM_HERE, base::BindOnce(...)); 478 479// This task has the highest priority. The thread pool will schedule it before 480// USER_VISIBLE and BEST_EFFORT tasks. 481base::ThreadPool::PostTask( 482 FROM_HERE, {base::TaskPriority::USER_BLOCKING}, 483 base::BindOnce(...)); 484 485// This task has the lowest priority and is allowed to block (e.g. it 486// can read a file from disk). 487base::ThreadPool::PostTask( 488 FROM_HERE, {base::TaskPriority::BEST_EFFORT, base::MayBlock()}, 489 base::BindOnce(...)); 490 491// This task blocks shutdown. The process won't exit before its 492// execution is complete. 493base::ThreadPool::PostTask( 494 FROM_HERE, {base::TaskShutdownBehavior::BLOCK_SHUTDOWN}, 495 base::BindOnce(...)); 496``` 497 498## Keeping the Browser Responsive 499 500Do not perform expensive work on the main thread, the IO thread or any sequence 501that is expected to run tasks with a low latency. Instead, perform expensive 502work asynchronously using `base::ThreadPool::PostTaskAndReply*()` or 503`base::SequencedTaskRunner::PostTaskAndReply()`. Note that 504asynchronous/overlapped I/O on the IO thread are fine. 505 506Example: Running the code below on the main thread will prevent the browser from 507responding to user input for a long time. 508 509```cpp 510// GetHistoryItemsFromDisk() may block for a long time. 511// AddHistoryItemsToOmniboxDropDown() updates the UI and therefore must 512// be called on the main thread. 513AddHistoryItemsToOmniboxDropdown(GetHistoryItemsFromDisk("keyword")); 514``` 515 516The code below solves the problem by scheduling a call to 517`GetHistoryItemsFromDisk()` in a thread pool followed by a call to 518`AddHistoryItemsToOmniboxDropdown()` on the origin sequence (the main thread in 519this case). The return value of the first call is automatically provided as 520argument to the second call. 521 522```cpp 523base::ThreadPool::PostTaskAndReplyWithResult( 524 FROM_HERE, {base::MayBlock()}, 525 base::BindOnce(&GetHistoryItemsFromDisk, "keyword"), 526 base::BindOnce(&AddHistoryItemsToOmniboxDropdown)); 527``` 528 529## Posting a Task with a Delay 530 531### Posting a One-Off Task with a Delay 532 533To post a task that must run once after a delay expires, use 534`base::ThreadPool::PostDelayedTask*()` or `base::TaskRunner::PostDelayedTask()`. 535 536```cpp 537base::ThreadPool::PostDelayedTask( 538 FROM_HERE, {base::TaskPriority::BEST_EFFORT}, base::BindOnce(&Task), 539 base::TimeDelta::FromHours(1)); 540 541scoped_refptr<base::SequencedTaskRunner> task_runner = 542 base::ThreadPool::CreateSequencedTaskRunner( 543 {base::TaskPriority::BEST_EFFORT}); 544task_runner->PostDelayedTask( 545 FROM_HERE, base::BindOnce(&Task), base::TimeDelta::FromHours(1)); 546``` 547 548*** note 549**NOTE:** A task that has a 1-hour delay probably doesn’t have to run right away 550when its delay expires. Specify `base::TaskPriority::BEST_EFFORT` to prevent it 551from slowing down the browser when its delay expires. 552*** 553 554### Posting a Repeating Task with a Delay 555To post a task that must run at regular intervals, 556use [`base::RepeatingTimer`](https://cs.chromium.org/chromium/src/base/timer/timer.h). 557 558```cpp 559class A { 560 public: 561 ~A() { 562 // The timer is stopped automatically when it is deleted. 563 } 564 void StartDoingStuff() { 565 timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1), 566 this, &MyClass::DoStuff); 567 } 568 void StopDoingStuff() { 569 timer_.Stop(); 570 } 571 private: 572 void DoStuff() { 573 // This method is called every second on the sequence that invoked 574 // StartDoingStuff(). 575 } 576 base::RepeatingTimer timer_; 577}; 578``` 579 580## Cancelling a Task 581 582### Using base::WeakPtr 583 584[`base::WeakPtr`](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h) 585can be used to ensure that any callback bound to an object is canceled when that 586object is destroyed. 587 588```cpp 589int Compute() { … } 590 591class A { 592 public: 593 void ComputeAndStore() { 594 // Schedule a call to Compute() in a thread pool followed by 595 // a call to A::Store() on the current sequence. The call to 596 // A::Store() is canceled when |weak_ptr_factory_| is destroyed. 597 // (guarantees that |this| will not be used-after-free). 598 base::ThreadPool::PostTaskAndReplyWithResult( 599 FROM_HERE, base::BindOnce(&Compute), 600 base::BindOnce(&A::Store, weak_ptr_factory_.GetWeakPtr())); 601 } 602 603 private: 604 void Store(int value) { value_ = value; } 605 606 int value_; 607 base::WeakPtrFactory<A> weak_ptr_factory_{this}; 608}; 609``` 610 611Note: `WeakPtr` is not thread-safe: `GetWeakPtr()`, `~WeakPtrFactory()`, and 612`Compute()` (bound to a `WeakPtr`) must all run on the same sequence. 613 614### Using base::CancelableTaskTracker 615 616[`base::CancelableTaskTracker`](https://cs.chromium.org/chromium/src/base/task/cancelable_task_tracker.h) 617allows cancellation to happen on a different sequence than the one on which 618tasks run. Keep in mind that `CancelableTaskTracker` cannot cancel tasks that 619have already started to run. 620 621```cpp 622auto task_runner = base::ThreadPool::CreateTaskRunner({}); 623base::CancelableTaskTracker cancelable_task_tracker; 624cancelable_task_tracker.PostTask(task_runner.get(), FROM_HERE, 625 base::DoNothing()); 626// Cancels Task(), only if it hasn't already started running. 627cancelable_task_tracker.TryCancelAll(); 628``` 629 630## Posting a Job to run in parallel 631 632The [`base::PostJob`](https://cs.chromium.org/chromium/src/base/task/post_job.h) 633is a power user API to be able to schedule a single base::RepeatingCallback 634worker task and request that ThreadPool workers invoke it concurrently. 635This avoids degenerate cases: 636* Calling `PostTask()` for each work item, causing significant overhead. 637* Fixed number of `PostTask()` calls that split the work and might run for a 638 long time. This is problematic when many components post “num cores” tasks and 639 all expect to use all the cores. In these cases, the scheduler lacks context 640 to be fair to multiple same-priority requests and/or ability to request lower 641 priority work to yield when high priority work comes in. 642 643```cpp 644// A canonical implementation of |worker_task|. 645void WorkerTask(base::JobDelegate* job_delegate) { 646 while (!job_delegate->ShouldYield()) { 647 auto work_item = TakeWorkItem(); // Smallest unit of work. 648 if (!work_item) 649 return: 650 ProcessWork(work_item); 651 } 652} 653 654// Returns the latest thread-safe number of incomplete work items. 655void NumIncompleteWorkItems(); 656 657base::PostJob(FROM_HERE, {}, 658 base::BindRepeating(&WorkerTask), 659 base::BindRepeating(&NumIncompleteWorkItems)); 660``` 661 662By doing as much work as possible in a loop when invoked, the worker task avoids 663scheduling overhead. Meanwhile `base::JobDelegate::ShouldYield()` is 664periodically invoked to conditionally exit and let the scheduler prioritize 665other work. This yield-semantic allows, for example, a user-visible job to use 666all cores but get out of the way when a user-blocking task comes in. 667 668### Adding additional work to a running job. 669 670When new work items are added and the API user wants additional threads to 671invoke the worker task concurrently, 672`JobHandle/JobDelegate::NotifyConcurrencyIncrease()` *must* be invoked shortly 673after max concurrency increases. 674 675## Testing 676 677For more details see [Testing Components Which Post 678Tasks](threading_and_tasks_testing.md). 679 680To test code that uses `base::ThreadTaskRunnerHandle`, 681`base::SequencedTaskRunnerHandle` or a function in 682[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h), 683instantiate a 684[`base::test::TaskEnvironment`](https://cs.chromium.org/chromium/src/base/test/task_environment.h) 685for the scope of the test. If you need BrowserThreads, use 686`content::BrowserTaskEnvironment` instead of 687`base::test::TaskEnvironment`. 688 689Tests can run the `base::test::TaskEnvironment`'s message pump using a 690`base::RunLoop`, which can be made to run until `Quit()` (explicitly or via 691`RunLoop::QuitClosure()`), or to `RunUntilIdle()` ready-to-run tasks and 692immediately return. 693 694TaskEnvironment configures RunLoop::Run() to GTEST_FAIL() if it hasn't been 695explicitly quit after TestTimeouts::action_timeout(). This is preferable to 696having the test hang if the code under test fails to trigger the RunLoop to 697quit. The timeout can be overridden with base::test::ScopedRunLoopTimeout. 698 699```cpp 700class MyTest : public testing::Test { 701 public: 702 // ... 703 protected: 704 base::test::TaskEnvironment task_environment_; 705}; 706 707TEST(MyTest, MyTest) { 708 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&A)); 709 base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE, 710 base::BindOnce(&B)); 711 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask( 712 FROM_HERE, base::BindOnce(&C), base::TimeDelta::Max()); 713 714 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until it is empty. 715 // Delayed tasks are not added to the queue until they are ripe for execution. 716 base::RunLoop().RunUntilIdle(); 717 // A and B have been executed. C is not ripe for execution yet. 718 719 base::RunLoop run_loop; 720 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&D)); 721 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure()); 722 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&E)); 723 724 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until QuitClosure is 725 // invoked. 726 run_loop.Run(); 727 // D and run_loop.QuitClosure() have been executed. E is still in the queue. 728 729 // Tasks posted to thread pool run asynchronously as they are posted. 730 base::ThreadPool::PostTask(FROM_HERE, {}, base::BindOnce(&F)); 731 auto task_runner = 732 base::ThreadPool::CreateSequencedTaskRunner({}); 733 task_runner->PostTask(FROM_HERE, base::BindOnce(&G)); 734 735 // To block until all tasks posted to thread pool are done running: 736 base::ThreadPoolInstance::Get()->FlushForTesting(); 737 // F and G have been executed. 738 739 base::ThreadPool::PostTaskAndReplyWithResult( 740 FROM_HERE, {}, base::BindOnce(&H), base::BindOnce(&I)); 741 742 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until both the 743 // (Thread|Sequenced)TaskRunnerHandle queue and the TaskSchedule queue are 744 // empty: 745 task_environment_.RunUntilIdle(); 746 // E, H, I have been executed. 747} 748``` 749 750## Using ThreadPool in a New Process 751 752ThreadPoolInstance needs to be initialized in a process before the functions in 753[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h) 754can be used. Initialization of ThreadPoolInstance in the Chrome browser process 755and child processes (renderer, GPU, utility) has already been taken care of. To 756use ThreadPoolInstance in another process, initialize ThreadPoolInstance early 757in the main function: 758 759```cpp 760// This initializes and starts ThreadPoolInstance with default params. 761base::ThreadPoolInstance::CreateAndStartWithDefaultParams(“process_name”); 762// The base/task/post_task.h API can now be used with base::ThreadPool trait. 763// Tasks will be // scheduled as they are posted. 764 765// This initializes ThreadPoolInstance. 766base::ThreadPoolInstance::Create(“process_name”); 767// The base/task/post_task.h API can now be used with base::ThreadPool trait. No 768// threads will be created and no tasks will be scheduled until after Start() is 769// called. 770base::ThreadPoolInstance::Get()->Start(params); 771// ThreadPool can now create threads and schedule tasks. 772``` 773 774And shutdown ThreadPoolInstance late in the main function: 775 776```cpp 777base::ThreadPoolInstance::Get()->Shutdown(); 778// Tasks posted with TaskShutdownBehavior::BLOCK_SHUTDOWN and 779// tasks posted with TaskShutdownBehavior::SKIP_ON_SHUTDOWN that 780// have started to run before the Shutdown() call have now completed their 781// execution. Tasks posted with 782// TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN may still be 783// running. 784``` 785## TaskRunner ownership (encourage no dependency injection) 786 787TaskRunners shouldn't be passed through several components. Instead, the 788components that uses a TaskRunner should be the one that creates it. 789 790See [this example](https://codereview.chromium.org/2885173002/) of a 791refactoring where a TaskRunner was passed through a lot of components only to be 792used in an eventual leaf. The leaf can and should now obtain its TaskRunner 793directly from 794[`base/task/post_task.h`](https://cs.chromium.org/chromium/src/base/task/post_task.h). 795 796As mentioned above, `base::test::TaskEnvironment` allows unit tests to 797control tasks posted from underlying TaskRunners. In rare cases where a test 798needs to more precisely control task ordering: dependency injection of 799TaskRunners can be useful. For such cases the preferred approach is the 800following: 801 802```cpp 803class Foo { 804 public: 805 806 // Overrides |background_task_runner_| in tests. 807 void SetBackgroundTaskRunnerForTesting( 808 scoped_refptr<base::SequencedTaskRunner> background_task_runner) { 809 background_task_runner_ = std::move(background_task_runner); 810 } 811 812 private: 813 scoped_refptr<base::SequencedTaskRunner> background_task_runner_ = 814 base::ThreadPool::CreateSequencedTaskRunner( 815 {base::MayBlock(), base::TaskPriority::BEST_EFFORT}); 816} 817``` 818 819Note that this still allows removing all layers of plumbing between //chrome and 820that component since unit tests will use the leaf layer directly. 821 822## FAQ 823See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more examples. 824 825[task APIs v3]: https://docs.google.com/document/d/1tssusPykvx3g0gvbvU4HxGyn3MjJlIylnsH13-Tv6s4/edit?ts=5de99a52#heading=h.ss4tw38hvh3s 826