summaryrefslogtreecommitdiff
path: root/chromium/docs/threading_and_tasks_faq.md
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-13 15:05:36 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-02-14 10:33:47 +0000
commite684a3455bcc29a6e3e66a004e352dea4e1141e7 (patch)
treed55b4003bde34d7d05f558f02cfd82b2a66a7aac /chromium/docs/threading_and_tasks_faq.md
parent2b94bfe47ccb6c08047959d1c26e392919550e86 (diff)
downloadqtwebengine-chromium-e684a3455bcc29a6e3e66a004e352dea4e1141e7.tar.gz
BASELINE: Update Chromium to 72.0.3626.110 and Ninja to 1.9.0
Change-Id: Ic57220b00ecc929a893c91f5cc552f5d3e99e922 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/docs/threading_and_tasks_faq.md')
-rw-r--r--chromium/docs/threading_and_tasks_faq.md105
1 files changed, 79 insertions, 26 deletions
diff --git a/chromium/docs/threading_and_tasks_faq.md b/chromium/docs/threading_and_tasks_faq.md
index 0084fcdc532..ac918435909 100644
--- a/chromium/docs/threading_and_tasks_faq.md
+++ b/chromium/docs/threading_and_tasks_faq.md
@@ -2,9 +2,12 @@
[TOC]
+Note: Make sure to read the main [Threading and Tasks](threading_and_tasks.md)
+docs first.
+
## 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`.
@@ -19,13 +22,13 @@ A task is posted through the `base/task/post_task.h` API with `TaskTraits`.
`CreateSingleThreadTaskRunnerWithTraits(..., mode)`:
* Where `mode` is `SingleThreadTaskRunnerThreadMode::DEDICATED`:
* 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.
* Where `mode` is `SingleThreadTaskRunnerThreadMode::SHARED`:
* The task runs on a thread that runs tasks from one or many
unrelated SingleThreadTaskRunners. This is not the main thread
- or the IO thread.
+ nor the IO thread.
* Otherwise:
* The task runs in a thread pool.
@@ -34,26 +37,20 @@ 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
dedicated thread.
-## Blocking off-CPU
+## Making blocking calls (which do not use the CPU)
-### How to make a call that may block off-CPU and never return?
+### How to make a blocking call without preventing other tasks from being scheduled?
-If you can't avoid making a call to a third-party library that may block off-CPU
-and never return, you must take some steps to ensure that it doesn't prevent
-other tasks from running. The steps depend on where the task runs (see [Where
-will a task run?](#On-what-thread-will-a-task-run_)).
+The steps depend on where the task runs (see [Where will a task run?](#On-what-thread-will-a-task-run_)).
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
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
that can run concurrently on the CPU. If the scope exits, the thread pool
- capacity goes back to normal. Since tasks posted to the same sequence can't
- run concurrently, it is advisable to run tasks that may block indefinitely in
- [parallel](threading_and_tasks.md#posting-a-parallel-task) rather than in
- [sequence](threading_and_tasks.md#posting-a-sequenced-task).
+ capacity goes back to normal.
If the task runs on the main thread, the IO thread or a `SHARED
SingleThreadTaskRunner`:
@@ -64,15 +61,69 @@ 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
- no-op that documents the blocking behavior. Tasks posted to the same
- `DEDICATED SingleThreadTaskRunner` won't run until your blocking task returns
- (they will never run if the blocking task never returns).
+ no-op that documents the blocking behavior (and makes it pass assertions).
+ Tasks posted to the same `DEDICATED SingleThreadTaskRunner` won't run until
+ 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
-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?
+
+If you can't avoid making a call to a third-party library that may block off-
+CPU, follow recommendations in [How to make a blocking call without affecting
+other tasks?](#How-to-make-a-blocking-call-without-affecting-other-tasks_).
+This ensures that a current task doesn't prevent other tasks from running even
+if it never returns.
+
+Since tasks posted to the same sequence can't run concurrently, it is advisable
+to run tasks that may block indefinitely in
+[parallel](threading_and_tasks.md#posting-a-parallel-task) rather than in
+[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?
+
+No. All blocking //base APIs (e.g. base::ReadFileToString, base::File::Read,
+base::SysInfo::AmountOfFreeDiskSpace, base::WaitableEvent::Wait, etc.) have their
+own internal annotations. See
+[base/threading/scoped_blocking_call.h](https://cs.chromium.org/chromium/src/base/threading/scoped_blocking_call.h).
+
+### Can multiple ScopedBlockingCall be nested for the purpose of documentation?
+
+Nested `ScopedBlockingCall` are supported. Most of the time, the inner
+ScopedBlockingCalls will no-op (the exception is WILL_BLOCK nested in MAY_BLOCK).
+As such, it is permitted to add a ScopedBlockingCall in the scope where a function
+that is already annotated is called for documentation purposes.:
+
+```cpp
+Data GetDataFromNetwork() {
+ ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
+ // Fetch data from network.
+ ...
+ return data;
+}
+
+void ProcessDataFromNetwork() {
+ Data data;
+ {
+ // Document the blocking behavior with a ScopedBlockingCall.
+ // Permitted, but not required since GetDataFromNetwork() is itself annotated.
+ ScopedBlockingCall scoped_blocking_call(BlockingType::MAY_BLOCK);
+ data = GetDataFromNetwork();
+ }
+ CPUIntensiveProcessing(data);
+}
+```
+
+ However, CPU usage should always be minimal within the scope of
+`ScopedBlockingCall`. See
+[base/threading/scoped_blocking_call.h](https://cs.chromium.org/chromium/src/base/threading/scoped_blocking_call.h).
+
## Sequences
@@ -89,15 +140,16 @@ The following mappings can be useful when migrating code from a
* BrowserThread::DeleteOnThread -> base::OnTaskRunnerDeleter / base::RefCountedDeleteOnSequence
* BrowserMessageFilter::OverrideThreadForMessage() -> BrowserMessageFilter::OverrideTaskRunnerForMessage()
* CreateSingleThreadTaskRunnerWithTraits() -> CreateSequencedTaskRunnerWithTraits()
- * Every CreateSingleThreadTaskRunnerWithTraits() usage should be accompanied
- with a comment and ideally a bug to make it sequence when the sequence-unfriendly
- dependency is addressed.
+ * Every CreateSingleThreadTaskRunnerWithTraits() usage, outside of
+ BrowserThread::UI/IO, should be accompanied with a comment and ideally a
+ bug to make it sequence when the sequence-unfriendly dependency is
+ addressed.
### How to ensure mutual exclusion between tasks posted by a component?
Create a `SequencedTaskRunner` using `CreateSequencedTaskRunnerWithTraits()` and
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
`Lazy(Sequenced|SingleThread|COMSTA)TaskRunner` in an anonymous namespace.
@@ -107,7 +159,7 @@ common `SequencedTaskRunner`, use
If the test uses `BrowserThread::UI/IO`, instantiate a
`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
`base::test::ScopedTaskEnvironment` for the scope of the test. Call
@@ -136,5 +188,6 @@ EXPECT_TRUE(g_condition);
## 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).