Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(2630)

Unified Diff: docs/threading_and_tasks.md

Issue 2875653003: Add "Threading and Tasks in Chrome" documentation. (Closed)
Patch Set: Created 3 years, 7 months ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View side-by-side diff with in-line comments
Download patch
« no previous file with comments | « docs/README.md ('k') | no next file » | no next file with comments »
Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
Index: docs/threading_and_tasks.md
diff --git a/docs/threading_and_tasks.md b/docs/threading_and_tasks.md
new file mode 100644
index 0000000000000000000000000000000000000000..986d78118cd6172118cdddd7945a13bba7762534
--- /dev/null
+++ b/docs/threading_and_tasks.md
@@ -0,0 +1,614 @@
+# Threading and Tasks in Chrome
+
+[TOC]
+
+## Overview
+
+### Threads
+
+Every Chrome process has
+
+* a main thread
+ * in the browser process: updates the UI
+ * in renderer processes: runs most of Blink
+* an IO thread
+ * in the browser process: handles IPCs and network requests
+ * in renderer processes: handles IPCs
+* a few more special-purpose threads
+* and a pool of general-purpose threads
+
+Most threads have a loop that gets tasks from a queue and runs them (the queue
+may be shared between multiple threads).
+
+### Tasks
+
+A task is a `base::OnceClosure` added to a queue for asynchronous execution.
+
+A `base::OnceClosure` stores a function pointer and arguments. It has a `Run()`
+method that invokes the function pointer using the bound arguments. It is
+created using `base::BindOnce`. (ref. [Callback<> and Bind()
+documentation](callback.md)).
+
+```
+void TaskA() {}
+void TaskB(int v) {}
+
+auto task_a = base::BindOnce(&TaskA);
+auto task_b = base::BindOnce(&TaskB, 42);
+```
+
+A group of tasks can be executed in one of the following ways:
+
+* [Parallel](#Posting-a-Parallel-Task): No task execution ordering, possibly all
+ at once on any thread
+* [Sequenced](#Posting-a-Sequenced-Task): Tasks executed in posting order, one
+ at a time on any thread.
+* [Single Threaded](#Posting-Multiple-Tasks-to-the-Same-Thread): Tasks executed
+ in posting order, one at a time on a single thread.
+ * [COM Single Threaded](#Posting-Tasks-to-a-COM-Single-Thread-Apartment-STA_Thread-Windows_):
+ A variant of single threaded with COM initialized.
+
+The discussion below covers all of these ways to execute tasks.
+
+## Posting a Parallel Task
+
+### Direct Posting to the Task Scheduler
+
+A task that can run on any thread and doesn’t have ordering or mutual exclusion
+requirements with other tasks should be posted using one of the
+`base::PostTask*()` functions defined in
+[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h).
+
+```cpp
+base::PostTask(FROM_HERE, base::BindOnce(&Task));
+```
+
+This posts tasks with default traits.
+
+The `base::PostTask*WithTraits()` functions allow the caller to provide
+additional details about the task via TaskTraits (ref.
+[Annotating Tasks with TaskTraits](#Annotating-Tasks-with-TaskTraits)).
+
+```cpp
+base::PostTaskWithTraits(
+ FROM_HERE, {base::TaskPriority::BACKGROUND, MayBlock()},
+ base::BindOnce(&Task));
+```
+
+## Posting via a TaskRunner
+
+A parallel
+[`TaskRunner`](https://cs.chromium.org/chromium/src/base/task_runner.h) is an
+alternative to calling `base::PostTask*()` directly. This is mainly useful when
+it isn’t known in advance whether tasks will be posted in parallel, in sequence,
+or to a single-thread (ref. [Posting a Sequenced Task](#Posting-a-Sequenced-
+Task), [Posting Multiple Tasks to the Same Thread](#Posting-Multiple-Tasks-to-
+the-Same-Thread)). Since `TaskRunner` is the base class of `SequencedTaskRunner`
+and `SingleThreadTaskRunner`, a `scoped_refptr<TaskRunner>` member can hold a
+`TaskRunner`, a `SequencedTaskRunner` or a `SingleThreadTaskRunner`.
+
+```cpp
+class A {
+ public:
+ A() = default;
+
+ void set_task_runner_for_testing(
+ scoped_refptr<base::TaskRunner> task_runner) {
+ task_runner_ = std::move(task_runner);
+ }
+
+ void DoSomething() {
+ // In production, A is always posted in parallel. In test, it is posted to
+ // the TaskRunner provided via set_task_runner_for_testing().
+ task_runner_->PostTask(FROM_HERE, base::BindOnce(&A));
+ }
+
+ private:
+ scoped_refptr<base::TaskRunner> task_runner_ =
+ base::CreateTaskRunnerWithTraits({base::TaskPriority::USER_VISIBLE});
+};
+```
+
+Unless a test needs to control precisely how tasks are executed, it is preferred
+to call `base::PostTask*()` directly (ref. [Testing](#Testing) for less invasive
+ways of controlling tasks in tests).
+
+## Posting a Sequenced Task
+
+A sequence is a set of tasks that run one at a time in posting order (not
+necessarily on the same thread). To post tasks as part of a sequence, use a
+ [`SequencedTaskRunner`](https://cs.chromium.org/chromium/src/base/sequenced_task_runner.h).
+
+### Posting to a New Sequence
+
+A `SequencedTaskRunner` can be created by
+`base::CreateSequencedTaskRunnerWithTraits()`.
+
+```cpp
+scoped_refptr<SequencedTaskRunner> sequenced_task_runner =
+ base::CreateSequencedTaskRunnerWithTraits(...);
+
+// TaskB runs after TaskA completes.
+sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
+sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
+```
+
+### Posting to the Current Sequence
+
+The `SequencedTaskRunner` to which the current task was posted can be obtained
+via
+[`SequencedTaskRunnerHandle::Get()`](https://cs.chromium.org/chromium/src/base/threading/sequenced_task_runner_handle.h).
+
+*** note
+**NOTE:** it is invalid to call `SequencedTaskRunnerHandle::Get()` from a
+parallel task, but it is valid from a single-threaded task (a
+`SingleThreadTaskRunner` is a `SequencedTaskRunner`).
+***
+
+```cpp
+// The task will run after any task that has already been posted
+// to the SequencedTaskRunner to which the current task was posted
+// (in particular, it will run after the current task completes).
+// It is also guaranteed that it won’t run concurrently with any
+// task posted to that SequencedTaskRunner.
+base::SequencedTaskRunnerHandle::Get()->
+ PostTask(FROM_HERE, base::BindOnce(&Task));
+```
+
+## Using Sequences Instead of Locks
+
+Usage of locks is discouraged in Chrome. Sequences inherently provide
+thread-safety. Prefer classes that are always accessed from the same sequence to
+managing your own thread-safety with locks.
+
+```cpp
+class A {
+ public:
+ A() {
+ // Do not require accesses to be on the creation sequence.
+ sequence_checker_.DetachFromSequence();
+ }
+
+ void AddValue(int v) {
+ // Check that all accesses are on the same sequence.
+ DCHECK(sequence_checker_.CalledOnValidSequence());
+ values_.push_back(v);
+}
+
+ private:
+ base::SequenceChecker sequence_checker_;
+
+ // No lock required, because all accesses are on the
+ // same sequence.
+ std::vector<int> values_;
+};
+
+A a;
+scoped_refptr<SequencedTaskRunner> task_runner_for_a = ...;
+task_runner->PostTask(FROM_HERE,
+ base::BindOnce(&A::AddValue, base::Unretained(&a)));
+task_runner->PostTask(FROM_HERE,
+ base::BindOnce(&A::AddValue, base::Unretained(&a)));
+
+// Access from a different sequence causes a DCHECK failure.
+scoped_refptr<SequencedTaskRunner> other_task_runner = ...;
+other_task_runner->PostTask(FROM_HERE,
+ base::BindOnce(&A::AddValue, base::Unretained(&a)));
+```
+
+## Posting Multiple Tasks to the Same Thread
+
+If multiple tasks need to run on the same thread, post them to a
+[`SingleThreadTaskRunner`](https://cs.chromium.org/chromium/src/base/single_thread_task_runner.h).
+All tasks posted to the same `SingleThreadTaskRunner` run on the same thread in
+posting order.
+
+### Posting to the Main Thread or to the IO Thread in the Browser Process
+
+To post tasks to the main thread or to the IO thread, get the appropriate
+SingleThreadTaskRunner using `content::BrowserThread::GetTaskRunnerForThread`.
+
+```cpp
+content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
+ ->PostTask(FROM_HERE, ...);
+
+content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO)
+ ->PostTask(FROM_HERE, ...);
+```
+
+The main thread and the IO thread are already super busy. Therefore, prefer
+posting to a general purpose thread when possible (ref. [Posting a Parallel
+Task](#Posting-a-Parallel-Task), [Posting a Sequenced task](#Posting-a
+-Sequenced-Task)). Good reasons to post to the main thread are to update the UI
+or access objects that are bound to it (e.g. `Profile`). A good reason to post
+to the IO thread is to access the internals of components that are bound to it
+(e.g. IPCs, network). Note: It is not necessary to have an explicit post task to
+the IO thread to send/receive an IPC or send/receive data on the network.
+
+### Posting to the Main Thread in a Renderer Process
+TODO
+
+### Posting to a Custom SingleThreadTaskRunner
+
+If multiple tasks need to run on the same thread and that thread doesn’t have to
+be the main thread or the IO thread, post them to a `SingleThreadTaskRunner`
+created by `base::CreateSingleThreadTaskRunnerWithTraits`.
+
+```cpp
+scoped_refptr<SequencedTaskRunner> single_thread_task_runner =
+ base::CreateSingleThreadTaskRunnerWithTraits(...);
+
+// TaskB runs after TaskA completes. Both tasks run on the same thread.
+single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
+single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
+```
+
+*** note
+**IMPORTANT:** You should rarely need this, most classes in Chromium require
+thread-safety (which sequences provide) not thread-affinity. If an API you’re
+using is incorrectly thread-affine (i.e. using
+[`base::ThreadChecker`](https://cs.chromium.org/chromium/src/base/threading/thread_checker.h)
+when it’s merely thread-unsafe and should use
+[`base::SequenceChecker`](https://cs.chromium.org/chromium/src/base/sequence_checker.h)),
+please consider fixing it instead of making things worse by also making your API thread-affine.
+***
+
+### Posting to the Current Thread
+
+*** note
+**IMPORTANT:** To post a task that needs mutual exclusion with the current
+sequence of tasks but doesn’t absolutely need to run on the current thread, use
+`SequencedTaskRunnerHandle::Get()` instead of `ThreadTaskRunnerHandle::Get()`
+(ref. [Posting to the Current Sequence](#Posting-to-the-Current-Sequence)). That
+will better document the requirements of the posted task. In a single-thread
+task, `SequencedTaskRunnerHandle::Get()` is equivalent to
+`ThreadTaskRunnerHandle::Get()`.
+***
+
+To post a task to the current thread, use [`ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h).
+
+```cpp
+// The task will run on the current thread in the future.
+base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&Task));
+```
+
+*** note
+**NOTE:** It is invalid to call `ThreadTaskRunnerHandle::Get()` from a parallel
+or a sequenced task.
+***
+
+## Posting Tasks to a COM Single-Thread Apartment (STA) Thread (Windows)
+
+Tasks that need to run on a COM Single-Thread Apartment (STA) thread must be
+posted to a `SingleThreadTaskRunner` returned by
+`CreateCOMSTATaskRunnerWithTraits()`. As mentioned in [Posting Multiple Tasks to
+the Same Thread](#Posting-Multiple-Tasks-to-the-Same-Thread), all tasks posted
+to the same `SingleThreadTaskRunner` run on the same thread in posting order.
+
+```cpp
+// Task(A|B|C)UsingCOMSTA will run on the same COM STA thread.
+
+void TaskAUsingCOMSTA() {
+ // [ This runs on a COM STA thread. ]
+
+ // Make COM STA calls.
+ // ...
+
+ // Post another task to the current COM STA thread.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&TaskCUsingCOMSTA));
+}
+void TaskBUsingCOMSTA() { }
+void TaskCUsingCOMSTA() { }
+
+auto com_sta_task_runner = base::CreateCOMSTATaskRunnerWithTraits(...);
+com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskAUsingCOMSTA));
+com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskBUsingCOMSTA));
+```
+
+## Annotating Tasks with TaskTraits
+
+[`TaskTraits`](https://cs.chromium.org/chromium/src/base/task_scheduler/task_traits.h)
+encapsulate information about a task that helps the task scheduler make better
+scheduling decisions.
+
+All `PostTask*()` functions in
+[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h)
+have an overload that takes `TaskTraits` as argument and one that doesn’t. The
+overload that doesn’t take `TaskTraits` as argument is appropriate for tasks
+that:
+- Don’t block (ref. MayBlock and WithBaseSyncPrimitives).
+- Prefer inheriting the current priority to specifying their own.
+- Can either block shutdown or be skipped on shutdown (task scheduler is free to choose a fitting default).
+Tasks that don’t match this description must be posted with explicit TaskTraits.
+
+[`base/task_scheduler/task_traits.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/task_traits.h)
+provides exhaustive documentation of available traits. Below are some examples
+of how to specify `TaskTraits`.
+
+```cpp
+// This task has no explicit TaskTraits. It cannot block. Its priority
+// is inherited from the calling context (e.g. if it is posted from
+// a BACKGROUND task, it will have a BACKGROUND priority). It will either
+// block shutdown or be skipped on shutdown.
+base::PostTask(FROM_HERE, base::BindOnce(...));
+
+// This task has the highest priority. The task scheduler will try to
+// run it before USER_VISIBLE and BACKGROUND tasks.
+base::PostTaskWithTraits(
+ FROM_HERE, {base::TaskPriority::USER_BLOCKING},
+ base::BindOnce(...));
+
+// This task has the lowest priority and is allowed to block (e.g. it
+// can read a file from disk).
+base::PostTaskWithTraits(
+ FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
+ base::BindOnce(...));
+
+// This task blocks shutdown. The process won't exit before its
+// execution is complete.
+base::PostTaskWithTraits(
+ FROM_HERE, {base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
+ base::BindOnce(...));
+```
+
+## Keeping the Browser Responsive
+
+Do not perform expensive work on the main thread, the IO thread or any sequence
+that is expected to run tasks with a low latency. Instead, perform expensive
+work asynchronously using `base::PostTaskAndReply*()` or
+`SequencedTaskRunner::PostTaskAndReply()`.
+
+Example: Running the code below on the main thread will prevent the browser from
+responding to user input for a long time.
+
+```cpp
+// GetHistoryItemsFromDisk() may block for a long time.
+// AddHistoryItemsToOmniboxDropDown() updates the UI and therefore must
+// be called on the main thread.
+AddHistoryItemsToOmniboxDropdown(GetHistoryItemsFromDisk("keyword"));
+```
+
+The code below solves the problem by scheduling a call to
+`GetHistoryItemsFromDisk()` in a thread pool followed by a call to
+`AddHistoryItemsToOmniboxDropdown()` on the origin sequence (the main thread in
+this case). The return value of the first call is automatically provided as
+argument to the second call.
+
+```cpp
+base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {base::MayBlock()},
+ base::BindOnce(&GetHistoryItemsFromDisk, "keyword"),
+ base::BindOnce(&AddHistoryItemsToOmniboxDropdown));
+```
+
+## Posting a Task with a Delay
+
+### Posting a One-Off Task with a Delay
+
+To post a task that must run once after a delay expires, use
+`base::PostDelayedTask*()` or `TaskRunner::PostDelayedTask()`.
+
+```cpp
+base::PostDelayedTaskWithTraits(
+ FROM_HERE, {base::TaskPriority::BACKGROUND}, base::BindOnce(&Task),
+ base::TimeDelta::FromHours(1));
+
+scoped_refptr<base::SequencedTaskRunner> task_runner =
+ base::CreateSequencedTaskRunnerWithTraits({base::TaskPriority::BACKGROUND});
+task_runner->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&Task), base::TimeDelta::FromHours(1));
+```
+
+*** note
+**NOTE:** A task that has a 1-hour delay probably doesn’t have to run right away
+when its delay expires. Specify `base::TaskPriority::BACKGROUND` to prevent it
+from slowing down the browser when its delay expires.
+***
+
+### Posting a Repeating Task with a Delay
+To post a task that must run at regular intervals,
+use [`base::RepeatingTimer`](https://cs.chromium.org/chromium/src/base/timer/timer.h).
+
+```cpp
+class A {
+ public:
+ ~A() {
+ // The timer is stopped automatically when it is deleted.
+ }
+ void StartDoingStuff() {
+ timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1),
+ this, &MyClass::DoStuff);
+ }
+ void StopDoingStuff() {
+ timer_.Stop();
+ }
+ private:
+ void DoStuff() {
+ // This method is called every second on the sequence that invoked
+ // StartDoingStuff().
+ }
+ base::RepeatingTimer timer_;
+};
+```
+
+## Cancelling a Task
+
+### Using base::WeakPtr
+
+[`base::WeakPtr`](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h)
+can be used to ensure that any callback bound to an object is canceled when that
+object is destroyed.
+
+```cpp
+int Compute() { … }
+
+class A {
+ public:
+ A() : weak_ptr_factory_(this) {}
+
+ void ComputeAndStore() {
+ // Schedule a call to Compute() in a thread pool followed by
+ // a call to A::Store() on the current sequence. The call to
+ // A::Store() is canceled when |weak_ptr_factory_| is destroyed.
+ // (guarantees that |this| will not be used-after-free).
+ base::PostTaskAndReplyWithResult(
+ FROM_HERE, base::BindOnce(&Compute),
+ base::BindOnce(&A::Store, weak_ptr_factory_.GetWeakPtr()));
+ }
+
+ private:
+ void Store(int value) { value_ = value; }
+
+ int value_;
+ base::WeakPtrFactory<A> weak_ptr_factory_;
+};
+```
+
+Note: `WeakPtr` is not thread-safe: `GetWeakPtr()`, `~WeakPtrFactory()`, and
+`Compute()` (bound to a `WeakPtr`) must all run on the same sequence.
+
+### Using base::CancelableTaskTracker
+
+[`base::CancelableTaskTracker`](https://cs.chromium.org/chromium/src/base/task/cancelable_task_tracker.h)
+allows cancellation to happen on a different sequence than the one on which
+tasks run. Keep in mind that `CancelableTaskTracker` cannot cancel tasks that
+have already started to run.
+
+```cpp
+auto task_runner = base::CreateTaskRunnerWithTraits(base::TaskTraits());
+base::CancelableTaskTracker cancelable_task_tracker;
+cancelable_task_tracker.PostTask(task_runner.get(), FROM_HERE,
+ base::Bind(&base::DoNothing));
+// Cancels Task(), only if it hasn't already started running.
+cancelable_task_tracker.TryCancelAll();
+```
+
+## Testing
+
+To test code that uses `base::ThreadTaskRunnerHandle`,
+`base::SequencedTaskRunnerHandle` or a function in
+[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h), instantiate a
+[`base::test::ScopedTaskEnvironment`](https://cs.chromium.org/chromium/src/base/test/scoped_task_environment.h)
+for the scope of the test.
+
+```cpp
+class MyTest : public testing::Test {
+ public:
+ // ...
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+};
+
+TEST(MyTest, MyTest) {
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&A));
+ base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
+ base::BindOnce(&B));
+ base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
+ FROM_HERE, base::BindOnce(&C), base::TimeDelta::Max());
+
+ // This runs the (Thread|Sequenced)TaskRunnerHandle queue until it is empty.
+ // Delayed tasks are not added to the queue until they are ripe for execution.
+ base::RunLoop().RunUntilIdle();
+ // A and B have been executed. C is not ripe for execution yet.
+
+ base::RunLoop run_loop;
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&D));
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&E));
+
+ // This runs the (Thread|Sequenced)TaskRunnerHandle queue until QuitClosure is
+ // invoked.
+ run_loop.Run();
+ // D and run_loop.QuitClosure() have been executed. E is still in the queue.
+
+ // Tasks posted to task scheduler run asynchronously as they are posted.
+ base::PostTaskWithTraits(FROM_HERE, base::TaskTraits(), base::BindOnce(&F));
+ auto task_runner =
+ base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits());
+ task_runner->PostTask(FROM_HERE, base::BindOnce(&G));
+
+ // To block until all tasks posted to task scheduler are done running:
+ base::TaskScheduler::GetInstance()->FlushForTesting();
+ // F and G have been executed.
+
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, base::TaskTrait(),
+ base::BindOnce(&H), base::BindOnce(&I));
+
+ // This runs the (Thread|Sequenced)TaskRunnerHandle queue until both the
+ // (Thread|Sequenced)TaskRunnerHandle queue and the TaskSchedule queue are
+ // empty:
+ scoped_task_environment_.RunUntilIdle();
+ // E, H, I have been executed.
+}
+```
+
+## Legacy Post Task APIs
+
+The Chrome browser process has a few legacy named threads (aka
+“BrowserThreads”). Each of these threads runs a specific type of task (e.g. the
+`FILE` thread handles low priority file operations, the `FILE_USER_BLOCKING`
+thread handles high priority file operations, the `CACHE` thread handles cache
+operations…). Usage of these named threads is now discouraged. New code should
+post tasks to task scheduler via
+[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h)
+instead.
+
+If for some reason you absolutely need to post a task to a legacy named thread
+(e.g. because it needs mutual exclusion with a task running on one of these
+threads), this is how you do it:
+
+```cpp
+content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::[IDENTIFIER])
+ ->PostTask(FROM_HERE, base::BindOnce(&Task));
+```
+
+Where `IDENTIFIER` is one of: `DB`, `FILE`, `FILE_USER_BLOCKING`, `PROCESS_LAUNCHER`, `CACHE`.
+
+The Chrome browser process has a “blocking pool” API:
+
+```cpp
+content::BrowserThread::PostBlockingPoolSequencedTask
+content::BrowserThread::GetBlockingPool
+```
+
+All tasks posted through this API are redirected to
+[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h).
+Therefore, there is no reason to add calls to this API.
+
+## Using TaskScheduler in a New Process
+
+TaskScheduler needs to be initialized in a process before the functions in
+[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h)
+can be used. Initialization of TaskScheduler in the Chrome browser process and
+child processes (renderer, GPU, utility) has already been taken care of. To use
+TaskScheduler in another process, initialize TaskScheduler early in the main
+function:
+
+```cpp
+// This initializes and starts TaskScheduler with default params.
+base::TaskScheduler::CreateAndStartWithDefaultParams(“process_name”);
+// The base/task_scheduler/post_task.h API can now be used. Tasks will be
+// scheduled as they are posted.
+
+// This initializes TaskScheduler.
+base::TaskScheduler::Create(“process_name”);
+// The base/task_scheduler/post_task.h API can now be used. No threads
+// will be created and no tasks will be scheduled until after Start() is called.
+base::TaskScheduler::GetInstance()->Start(params);
+// TaskScheduler can now create threads and schedule tasks.
+```
+
+And shutdown TaskScheduler late in the main function:
+
+```cpp
+base::TaskScheduler::GetInstance()->Shutdown();
+// Tasks posted with TaskShutdownBehavior::BLOCK_SHUTDOWN and
+// tasks posted with TaskShutdownBehavior::SKIP_ON_SHUTDOWN that
+// have started to run before the Shutdown() call have now completed their
+// execution. Tasks posted with
+// TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN may still be
+// running.
+```
« no previous file with comments | « docs/README.md ('k') | no next file » | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698