Commit 8917f4cc authored by Gabriel Charette's avatar Gabriel Charette Committed by Commit Bot

[Threading docs] Cross-reference FAQ and main docs

and follow-up on nits to https://chromium-review.googlesource.com/c/chromium/src/+/1261855

R=fdoray@chromium.org

Change-Id: I2ca5305af71fa89e13be10e40779641362529a42
Reviewed-on: https://chromium-review.googlesource.com/c/1342770
Commit-Queue: François Doray <fdoray@chromium.org>
Reviewed-by: default avatarFrançois Doray <fdoray@chromium.org>
Cr-Commit-Position: refs/heads/master@{#610416}
parent 41ddf490
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
[TOC] [TOC]
Note: See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more
examples.
## Overview ## Overview
Chromium is a very multithreaded product. We try to keep the UI as responsive as Chromium is a very multithreaded product. We try to keep the UI as responsive as
...@@ -77,7 +80,7 @@ use of base::CreateSingleThreadTaskRunnerWithTraits() with a TODO against your ...@@ -77,7 +80,7 @@ use of base::CreateSingleThreadTaskRunnerWithTraits() with a TODO against your
bug to use base::CreateSequencedTaskRunnerWithTraits() when fixed). bug to use base::CreateSequencedTaskRunnerWithTraits() when fixed).
Detailed documentation on how to migrate from single-threaded contexts to Detailed documentation on how to migrate from single-threaded contexts to
sequenced contexts can be found [here](threading_and_tasks_faq.md#How-can-I-migrate-from-SingleThreadTaskRunner-to-SequencedTaskRunner_). sequenced contexts can be found [here](threading_and_tasks_faq.md#How-to-migrate-from-SingleThreadTaskRunner-to-SequencedTaskRunner).
The discussion below covers all of these ways to execute tasks in details. The discussion below covers all of these ways to execute tasks in details.
...@@ -677,3 +680,6 @@ class FooWithCustomizableTaskRunnerForTesting { ...@@ -677,3 +680,6 @@ class FooWithCustomizableTaskRunnerForTesting {
Note that this still allows removing all layers of plumbing between //chrome and Note that this still allows removing all layers of plumbing between //chrome and
that component since unit tests will use the leaf layer directly. that component since unit tests will use the leaf layer directly.
## FAQ
See [Threading and Tasks FAQ](threading_and_tasks_faq.md) for more examples.
...@@ -2,9 +2,12 @@ ...@@ -2,9 +2,12 @@
[TOC] [TOC]
Note: Make sure to read the main [Threading and Tasks](threading_and_tasks.md)
docs first.
## General ## General
### On what thread will a task run? ### On which thread will a task run?
A task is posted through the `base/task/post_task.h` API with `TaskTraits`. A task is posted through the `base/task/post_task.h` API with `TaskTraits`.
...@@ -19,13 +22,13 @@ A task is posted through the `base/task/post_task.h` API with `TaskTraits`. ...@@ -19,13 +22,13 @@ A task is posted through the `base/task/post_task.h` API with `TaskTraits`.
`CreateSingleThreadTaskRunnerWithTraits(..., mode)`: `CreateSingleThreadTaskRunnerWithTraits(..., mode)`:
* Where `mode` is `SingleThreadTaskRunnerThreadMode::DEDICATED`: * Where `mode` is `SingleThreadTaskRunnerThreadMode::DEDICATED`:
* The task runs on a thread that only runs tasks from that * The task runs on a thread that only runs tasks from that
SingleThreadTaskRunner. This is not the main thread or the IO SingleThreadTaskRunner. This is not the main thread nor the IO
thread. thread.
* Where `mode` is `SingleThreadTaskRunnerThreadMode::SHARED`: * Where `mode` is `SingleThreadTaskRunnerThreadMode::SHARED`:
* The task runs on a thread that runs tasks from one or many * The task runs on a thread that runs tasks from one or many
unrelated SingleThreadTaskRunners. This is not the main thread unrelated SingleThreadTaskRunners. This is not the main thread
or the IO thread. nor the IO thread.
* Otherwise: * Otherwise:
* The task runs in a thread pool. * The task runs in a thread pool.
...@@ -34,7 +37,7 @@ As explained in [Prefer Sequences to Threads](threading_and_tasks.md#Prefer-Sequ ...@@ -34,7 +37,7 @@ As explained in [Prefer Sequences to Threads](threading_and_tasks.md#Prefer-Sequ
tasks should generally run on a sequence in a thread pool rather than on a tasks should generally run on a sequence in a thread pool rather than on a
dedicated thread. dedicated thread.
## Blocking off-CPU ## Making blocking calls (which do not use the CPU)
### How to make a blocking call without preventing other tasks from being scheduled? ### How to make a blocking call without preventing other tasks from being scheduled?
...@@ -42,7 +45,7 @@ The steps depend on where the task runs (see [Where will a task run?](#On-what-t ...@@ -42,7 +45,7 @@ The steps depend on where the task runs (see [Where will a task run?](#On-what-t
If the task runs in a thread pool: If the task runs in a thread pool:
* Annotate the scope that may block off-CPU with * Annotate the scope that may block with
`ScopedBlockingCall(BlockingType::MAY_BLOCK/WILL_BLOCK)`. A few milliseconds `ScopedBlockingCall(BlockingType::MAY_BLOCK/WILL_BLOCK)`. A few milliseconds
after the annotated scope is entered, the capacity of the thread pool is after the annotated scope is entered, the capacity of the thread pool is
incremented. This ensures that your task doesn't reduce the number of tasks incremented. This ensures that your task doesn't reduce the number of tasks
...@@ -58,15 +61,16 @@ SingleThreadTaskRunner`: ...@@ -58,15 +61,16 @@ SingleThreadTaskRunner`:
If the task runs on a `DEDICATED SingleThreadTaskRunner`: If the task runs on a `DEDICATED SingleThreadTaskRunner`:
* Annotate the scope that may block off-CPU with * Annotate the scope that may block with
`ScopedBlockingCall(BlockingType::MAY_BLOCK/WILL_BLOCK)`. The annotation is a `ScopedBlockingCall(BlockingType::MAY_BLOCK/WILL_BLOCK)`. The annotation is a
no-op that documents the blocking behavior. Tasks posted to the same no-op that documents the blocking behavior (and makes it pass assertions).
`DEDICATED SingleThreadTaskRunner` won't run until your blocking task returns Tasks posted to the same `DEDICATED SingleThreadTaskRunner` won't run until
(they will never run if the blocking task never returns). your blocking task returns (they will never run if the blocking task never
returns).
[base/threading/scoped_blocking_call.h](https://cs.chromium.org/chromium/src/base/threading/scoped_blocking_call.h) [base/threading/scoped_blocking_call.h](https://cs.chromium.org/chromium/src/base/threading/scoped_blocking_call.h)
explains the difference between `MAY_BLOCK ` and `WILL_BLOCK` and gives explains the difference between `MAY_BLOCK ` and `WILL_BLOCK` and gives
examples of off-CPU blocking operations. examples of blocking operations.
### How to make a blocking call that may never return without preventing other tasks from being scheduled? ### How to make a blocking call that may never return without preventing other tasks from being scheduled?
...@@ -79,7 +83,8 @@ if it never returns. ...@@ -79,7 +83,8 @@ if it never returns.
Since tasks posted to the same sequence can't run concurrently, it is advisable Since tasks posted to the same sequence can't run concurrently, it is advisable
to run tasks that may block indefinitely in to run tasks that may block indefinitely in
[parallel](threading_and_tasks.md#posting-a-parallel-task) rather than in [parallel](threading_and_tasks.md#posting-a-parallel-task) rather than in
[sequence](threading_and_tasks.md#posting-a-sequenced-task). [sequence](threading_and_tasks.md#posting-a-sequenced-task) (unless posting many
such tasks at which point sequencing can be a useful tool to prevent flooding).
### Do calls to blocking //base APIs need to be annotated with ScopedBlockingCall? ### Do calls to blocking //base APIs need to be annotated with ScopedBlockingCall?
...@@ -135,15 +140,16 @@ The following mappings can be useful when migrating code from a ...@@ -135,15 +140,16 @@ The following mappings can be useful when migrating code from a
* BrowserThread::DeleteOnThread -> base::OnTaskRunnerDeleter / base::RefCountedDeleteOnSequence * BrowserThread::DeleteOnThread -> base::OnTaskRunnerDeleter / base::RefCountedDeleteOnSequence
* BrowserMessageFilter::OverrideThreadForMessage() -> BrowserMessageFilter::OverrideTaskRunnerForMessage() * BrowserMessageFilter::OverrideThreadForMessage() -> BrowserMessageFilter::OverrideTaskRunnerForMessage()
* CreateSingleThreadTaskRunnerWithTraits() -> CreateSequencedTaskRunnerWithTraits() * CreateSingleThreadTaskRunnerWithTraits() -> CreateSequencedTaskRunnerWithTraits()
* Every CreateSingleThreadTaskRunnerWithTraits() usage should be accompanied * Every CreateSingleThreadTaskRunnerWithTraits() usage, outside of
with a comment and ideally a bug to make it sequence when the sequence-unfriendly BrowserThread::UI/IO, should be accompanied with a comment and ideally a
dependency is addressed. bug to make it sequence when the sequence-unfriendly dependency is
addressed.
### How to ensure mutual exclusion between tasks posted by a component? ### How to ensure mutual exclusion between tasks posted by a component?
Create a `SequencedTaskRunner` using `CreateSequencedTaskRunnerWithTraits()` and Create a `SequencedTaskRunner` using `CreateSequencedTaskRunnerWithTraits()` and
store it on an object that can be accessed from all the PostTask() call sites store it on an object that can be accessed from all the PostTask() call sites
that require mutual exclusion. If there isn't a shared object that can own that require mutual exclusion. If there isn't a shared object that can own a
common `SequencedTaskRunner`, use common `SequencedTaskRunner`, use
`Lazy(Sequenced|SingleThread|COMSTA)TaskRunner` in an anonymous namespace. `Lazy(Sequenced|SingleThread|COMSTA)TaskRunner` in an anonymous namespace.
...@@ -153,7 +159,7 @@ common `SequencedTaskRunner`, use ...@@ -153,7 +159,7 @@ common `SequencedTaskRunner`, use
If the test uses `BrowserThread::UI/IO`, instantiate a If the test uses `BrowserThread::UI/IO`, instantiate a
`content::TestBrowserThreadBundle` for the scope of the test. Call `content::TestBrowserThreadBundle` for the scope of the test. Call
`content::RunAllTasksUntilIdle()` to wait until all tasks have run. `TestBrowserThreadBundle::RunUntilIdle()` to wait until all tasks have run.
If the test doesn't use `BrowserThread::UI/IO`, instantiate a If the test doesn't use `BrowserThread::UI/IO`, instantiate a
`base::test::ScopedTaskEnvironment` for the scope of the test. Call `base::test::ScopedTaskEnvironment` for the scope of the test. Call
...@@ -182,5 +188,6 @@ EXPECT_TRUE(g_condition); ...@@ -182,5 +188,6 @@ EXPECT_TRUE(g_condition);
## Your question hasn't been answered? ## Your question hasn't been answered?
Ping 1. Check the main [Threading and Tasks](threading_and_tasks.md) docs.
2. Ping
[scheduler-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/scheduler-dev). [scheduler-dev@chromium.org](https://groups.google.com/a/chromium.org/forum/#!forum/scheduler-dev).
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment