blob: a61973011c2dd7c6a4afdef3654cba9c347cc9a7 [file] [log] [blame] [view]
fdoraybacba4a22017-05-10 21:10:001# Threading and Tasks in Chrome
2
3[TOC]
4
5## Overview
6
7### Threads
8
9Every Chrome process has
10
11* a main thread
12 * in the browser process: updates the UI
13 * in renderer processes: runs most of Blink
14* an IO thread
15 * in the browser process: handles IPCs and network requests
16 * in renderer processes: handles IPCs
17* a few more special-purpose threads
18* and a pool of general-purpose threads
19
20Most threads have a loop that gets tasks from a queue and runs them (the queue
21may be shared between multiple threads).
22
23### Tasks
24
25A task is a `base::OnceClosure` added to a queue for asynchronous execution.
26
27A `base::OnceClosure` stores a function pointer and arguments. It has a `Run()`
28method that invokes the function pointer using the bound arguments. It is
29created using `base::BindOnce`. (ref. [Callback<> and Bind()
30documentation](callback.md)).
31
32```
33void TaskA() {}
34void TaskB(int v) {}
35
36auto task_a = base::BindOnce(&TaskA);
37auto task_b = base::BindOnce(&TaskB, 42);
38```
39
40A group of tasks can be executed in one of the following ways:
41
42* [Parallel](#Posting-a-Parallel-Task): No task execution ordering, possibly all
43 at once on any thread
44* [Sequenced](#Posting-a-Sequenced-Task): Tasks executed in posting order, one
45 at a time on any thread.
46* [Single Threaded](#Posting-Multiple-Tasks-to-the-Same-Thread): Tasks executed
47 in posting order, one at a time on a single thread.
48 * [COM Single Threaded](#Posting-Tasks-to-a-COM-Single-Thread-Apartment-STA_Thread-Windows_):
49 A variant of single threaded with COM initialized.
50
51The discussion below covers all of these ways to execute tasks.
52
53## Posting a Parallel Task
54
55### Direct Posting to the Task Scheduler
56
57A task that can run on any thread and doesnt have ordering or mutual exclusion
58requirements with other tasks should be posted using one of the
59`base::PostTask*()` functions defined in
60[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h).
61
62```cpp
63base::PostTask(FROM_HERE, base::BindOnce(&Task));
64```
65
66This posts tasks with default traits.
67
68The `base::PostTask*WithTraits()` functions allow the caller to provide
69additional details about the task via TaskTraits (ref.
70[Annotating Tasks with TaskTraits](#Annotating-Tasks-with-TaskTraits)).
71
72```cpp
73base::PostTaskWithTraits(
74 FROM_HERE, {base::TaskPriority::BACKGROUND, MayBlock()},
75 base::BindOnce(&Task));
76```
77
fdoray52bf5552017-05-11 12:43:5978### Posting via a TaskRunner
fdoraybacba4a22017-05-10 21:10:0079
80A parallel
81[`TaskRunner`](https://cs.chromium.org/chromium/src/base/task_runner.h) is an
82alternative to calling `base::PostTask*()` directly. This is mainly useful when
83it isnt known in advance whether tasks will be posted in parallel, in sequence,
fdoray52bf5552017-05-11 12:43:5984or to a single-thread (ref.
85[Posting a Sequenced Task](#Posting-a-Sequenced-Task),
86[Posting Multiple Tasks to the Same Thread](#Posting-Multiple-Tasks-to-the-Same-Thread)).
87Since `TaskRunner` is the base class of `SequencedTaskRunner` and
88`SingleThreadTaskRunner`, a `scoped_refptr<TaskRunner>` member can hold a
fdoraybacba4a22017-05-10 21:10:0089`TaskRunner`, a `SequencedTaskRunner` or a `SingleThreadTaskRunner`.
90
91```cpp
92class A {
93 public:
94 A() = default;
95
96 void set_task_runner_for_testing(
97 scoped_refptr<base::TaskRunner> task_runner) {
98 task_runner_ = std::move(task_runner);
99 }
100
101 void DoSomething() {
102 // In production, A is always posted in parallel. In test, it is posted to
103 // the TaskRunner provided via set_task_runner_for_testing().
104 task_runner_->PostTask(FROM_HERE, base::BindOnce(&A));
105 }
106
107 private:
108 scoped_refptr<base::TaskRunner> task_runner_ =
109 base::CreateTaskRunnerWithTraits({base::TaskPriority::USER_VISIBLE});
110};
111```
112
113Unless a test needs to control precisely how tasks are executed, it is preferred
114to call `base::PostTask*()` directly (ref. [Testing](#Testing) for less invasive
115ways of controlling tasks in tests).
116
117## Posting a Sequenced Task
118
119A sequence is a set of tasks that run one at a time in posting order (not
120necessarily on the same thread). To post tasks as part of a sequence, use a
121 [`SequencedTaskRunner`](https://cs.chromium.org/chromium/src/base/sequenced_task_runner.h).
122
123### Posting to a New Sequence
124
125A `SequencedTaskRunner` can be created by
126`base::CreateSequencedTaskRunnerWithTraits()`.
127
128```cpp
129scoped_refptr<SequencedTaskRunner> sequenced_task_runner =
130 base::CreateSequencedTaskRunnerWithTraits(...);
131
132// TaskB runs after TaskA completes.
133sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
134sequenced_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
135```
136
137### Posting to the Current Sequence
138
139The `SequencedTaskRunner` to which the current task was posted can be obtained
140via
141[`SequencedTaskRunnerHandle::Get()`](https://cs.chromium.org/chromium/src/base/threading/sequenced_task_runner_handle.h).
142
143*** note
144**NOTE:** it is invalid to call `SequencedTaskRunnerHandle::Get()` from a
145parallel task, but it is valid from a single-threaded task (a
146`SingleThreadTaskRunner` is a `SequencedTaskRunner`).
147***
148
149```cpp
150// The task will run after any task that has already been posted
151// to the SequencedTaskRunner to which the current task was posted
152// (in particular, it will run after the current task completes).
153// It is also guaranteed that it won’t run concurrently with any
154// task posted to that SequencedTaskRunner.
155base::SequencedTaskRunnerHandle::Get()->
156 PostTask(FROM_HERE, base::BindOnce(&Task));
157```
158
159## Using Sequences Instead of Locks
160
161Usage of locks is discouraged in Chrome. Sequences inherently provide
162thread-safety. Prefer classes that are always accessed from the same sequence to
163managing your own thread-safety with locks.
164
165```cpp
166class A {
167 public:
168 A() {
169 // Do not require accesses to be on the creation sequence.
170 sequence_checker_.DetachFromSequence();
171 }
172
173 void AddValue(int v) {
174 // Check that all accesses are on the same sequence.
175 DCHECK(sequence_checker_.CalledOnValidSequence());
176 values_.push_back(v);
177}
178
179 private:
180 base::SequenceChecker sequence_checker_;
181
182 // No lock required, because all accesses are on the
183 // same sequence.
184 std::vector<int> values_;
185};
186
187A a;
188scoped_refptr<SequencedTaskRunner> task_runner_for_a = ...;
189task_runner->PostTask(FROM_HERE,
190 base::BindOnce(&A::AddValue, base::Unretained(&a)));
191task_runner->PostTask(FROM_HERE,
192 base::BindOnce(&A::AddValue, base::Unretained(&a)));
193
194// Access from a different sequence causes a DCHECK failure.
195scoped_refptr<SequencedTaskRunner> other_task_runner = ...;
196other_task_runner->PostTask(FROM_HERE,
197 base::BindOnce(&A::AddValue, base::Unretained(&a)));
198```
199
200## Posting Multiple Tasks to the Same Thread
201
202If multiple tasks need to run on the same thread, post them to a
203[`SingleThreadTaskRunner`](https://cs.chromium.org/chromium/src/base/single_thread_task_runner.h).
204All tasks posted to the same `SingleThreadTaskRunner` run on the same thread in
205posting order.
206
207### Posting to the Main Thread or to the IO Thread in the Browser Process
208
209To post tasks to the main thread or to the IO thread, get the appropriate
210SingleThreadTaskRunner using `content::BrowserThread::GetTaskRunnerForThread`.
211
212```cpp
213content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::UI)
214 ->PostTask(FROM_HERE, ...);
215
216content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::IO)
217 ->PostTask(FROM_HERE, ...);
218```
219
220The main thread and the IO thread are already super busy. Therefore, prefer
fdoray52bf5552017-05-11 12:43:59221posting to a general purpose thread when possible (ref.
222[Posting a Parallel Task](#Posting-a-Parallel-Task),
223[Posting a Sequenced task](#Posting-a-Sequenced-Task)).
224Good reasons to post to the main thread are to update the UI or access objects
225that are bound to it (e.g. `Profile`). A good reason to post to the IO thread is
226to access the internals of components that are bound to it (e.g. IPCs, network).
227Note: It is not necessary to have an explicit post task to the IO thread to
228send/receive an IPC or send/receive data on the network.
fdoraybacba4a22017-05-10 21:10:00229
230### Posting to the Main Thread in a Renderer Process
231TODO
232
233### Posting to a Custom SingleThreadTaskRunner
234
235If multiple tasks need to run on the same thread and that thread doesnt have to
236be the main thread or the IO thread, post them to a `SingleThreadTaskRunner`
237created by `base::CreateSingleThreadTaskRunnerWithTraits`.
238
239```cpp
240scoped_refptr<SequencedTaskRunner> single_thread_task_runner =
241 base::CreateSingleThreadTaskRunnerWithTraits(...);
242
243// TaskB runs after TaskA completes. Both tasks run on the same thread.
244single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskA));
245single_thread_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskB));
246```
247
248*** note
249**IMPORTANT:** You should rarely need this, most classes in Chromium require
250thread-safety (which sequences provide) not thread-affinity. If an API youre
251using is incorrectly thread-affine (i.e. using
252[`base::ThreadChecker`](https://cs.chromium.org/chromium/src/base/threading/thread_checker.h)
253when its merely thread-unsafe and should use
254[`base::SequenceChecker`](https://cs.chromium.org/chromium/src/base/sequence_checker.h)),
255please consider fixing it instead of making things worse by also making your API thread-affine.
256***
257
258### Posting to the Current Thread
259
260*** note
261**IMPORTANT:** To post a task that needs mutual exclusion with the current
262sequence of tasks but doesnt absolutely need to run on the current thread, use
263`SequencedTaskRunnerHandle::Get()` instead of `ThreadTaskRunnerHandle::Get()`
264(ref. [Posting to the Current Sequence](#Posting-to-the-Current-Sequence)). That
265will better document the requirements of the posted task. In a single-thread
266task, `SequencedTaskRunnerHandle::Get()` is equivalent to
267`ThreadTaskRunnerHandle::Get()`.
268***
269
270To post a task to the current thread, use [`ThreadTaskRunnerHandle`](https://cs.chromium.org/chromium/src/base/threading/thread_task_runner_handle.h).
271
272```cpp
273// The task will run on the current thread in the future.
274base::ThreadTaskRunnerHandle::Get()->PostTask(
275 FROM_HERE, base::BindOnce(&Task));
276```
277
278*** note
279**NOTE:** It is invalid to call `ThreadTaskRunnerHandle::Get()` from a parallel
280or a sequenced task.
281***
282
283## Posting Tasks to a COM Single-Thread Apartment (STA) Thread (Windows)
284
285Tasks that need to run on a COM Single-Thread Apartment (STA) thread must be
286posted to a `SingleThreadTaskRunner` returned by
287`CreateCOMSTATaskRunnerWithTraits()`. As mentioned in [Posting Multiple Tasks to
288the Same Thread](#Posting-Multiple-Tasks-to-the-Same-Thread), all tasks posted
289to the same `SingleThreadTaskRunner` run on the same thread in posting order.
290
291```cpp
292// Task(A|B|C)UsingCOMSTA will run on the same COM STA thread.
293
294void TaskAUsingCOMSTA() {
295 // [ This runs on a COM STA thread. ]
296
297 // Make COM STA calls.
298 // ...
299
300 // Post another task to the current COM STA thread.
301 base::ThreadTaskRunnerHandle::Get()->PostTask(
302 FROM_HERE, base::BindOnce(&TaskCUsingCOMSTA));
303}
304void TaskBUsingCOMSTA() { }
305void TaskCUsingCOMSTA() { }
306
307auto com_sta_task_runner = base::CreateCOMSTATaskRunnerWithTraits(...);
308com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskAUsingCOMSTA));
309com_sta_task_runner->PostTask(FROM_HERE, base::BindOnce(&TaskBUsingCOMSTA));
310```
311
312## Annotating Tasks with TaskTraits
313
314[`TaskTraits`](https://cs.chromium.org/chromium/src/base/task_scheduler/task_traits.h)
315encapsulate information about a task that helps the task scheduler make better
316scheduling decisions.
317
318All `PostTask*()` functions in
319[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h)
320have an overload that takes `TaskTraits` as argument and one that doesnt. The
321overload that doesnt take `TaskTraits` as argument is appropriate for tasks
322that:
323- Dont block (ref. MayBlock and WithBaseSyncPrimitives).
324- Prefer inheriting the current priority to specifying their own.
325- Can either block shutdown or be skipped on shutdown (task scheduler is free to choose a fitting default).
326Tasks that dont match this description must be posted with explicit TaskTraits.
327
328[`base/task_scheduler/task_traits.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/task_traits.h)
329provides exhaustive documentation of available traits. Below are some examples
330of how to specify `TaskTraits`.
331
332```cpp
333// This task has no explicit TaskTraits. It cannot block. Its priority
334// is inherited from the calling context (e.g. if it is posted from
335// a BACKGROUND task, it will have a BACKGROUND priority). It will either
336// block shutdown or be skipped on shutdown.
337base::PostTask(FROM_HERE, base::BindOnce(...));
338
339// This task has the highest priority. The task scheduler will try to
340// run it before USER_VISIBLE and BACKGROUND tasks.
341base::PostTaskWithTraits(
342 FROM_HERE, {base::TaskPriority::USER_BLOCKING},
343 base::BindOnce(...));
344
345// This task has the lowest priority and is allowed to block (e.g. it
346// can read a file from disk).
347base::PostTaskWithTraits(
348 FROM_HERE, {base::TaskPriority::BACKGROUND, base::MayBlock()},
349 base::BindOnce(...));
350
351// This task blocks shutdown. The process won't exit before its
352// execution is complete.
353base::PostTaskWithTraits(
354 FROM_HERE, {base::TaskShutdownBehavior::BLOCK_SHUTDOWN},
355 base::BindOnce(...));
356```
357
358## Keeping the Browser Responsive
359
360Do not perform expensive work on the main thread, the IO thread or any sequence
361that is expected to run tasks with a low latency. Instead, perform expensive
362work asynchronously using `base::PostTaskAndReply*()` or
363`SequencedTaskRunner::PostTaskAndReply()`.
364
365Example: Running the code below on the main thread will prevent the browser from
366responding to user input for a long time.
367
368```cpp
369// GetHistoryItemsFromDisk() may block for a long time.
370// AddHistoryItemsToOmniboxDropDown() updates the UI and therefore must
371// be called on the main thread.
372AddHistoryItemsToOmniboxDropdown(GetHistoryItemsFromDisk("keyword"));
373```
374
375The code below solves the problem by scheduling a call to
376`GetHistoryItemsFromDisk()` in a thread pool followed by a call to
377`AddHistoryItemsToOmniboxDropdown()` on the origin sequence (the main thread in
378this case). The return value of the first call is automatically provided as
379argument to the second call.
380
381```cpp
382base::PostTaskWithTraitsAndReplyWithResult(
383 FROM_HERE, {base::MayBlock()},
384 base::BindOnce(&GetHistoryItemsFromDisk, "keyword"),
385 base::BindOnce(&AddHistoryItemsToOmniboxDropdown));
386```
387
388## Posting a Task with a Delay
389
390### Posting a One-Off Task with a Delay
391
392To post a task that must run once after a delay expires, use
393`base::PostDelayedTask*()` or `TaskRunner::PostDelayedTask()`.
394
395```cpp
396base::PostDelayedTaskWithTraits(
397 FROM_HERE, {base::TaskPriority::BACKGROUND}, base::BindOnce(&Task),
398 base::TimeDelta::FromHours(1));
399
400scoped_refptr<base::SequencedTaskRunner> task_runner =
401 base::CreateSequencedTaskRunnerWithTraits({base::TaskPriority::BACKGROUND});
402task_runner->PostDelayedTask(
403 FROM_HERE, base::BindOnce(&Task), base::TimeDelta::FromHours(1));
404```
405
406*** note
407**NOTE:** A task that has a 1-hour delay probably doesnt have to run right away
408when its delay expires. Specify `base::TaskPriority::BACKGROUND` to prevent it
409from slowing down the browser when its delay expires.
410***
411
412### Posting a Repeating Task with a Delay
413To post a task that must run at regular intervals,
414use [`base::RepeatingTimer`](https://cs.chromium.org/chromium/src/base/timer/timer.h).
415
416```cpp
417class A {
418 public:
419 ~A() {
420 // The timer is stopped automatically when it is deleted.
421 }
422 void StartDoingStuff() {
423 timer_.Start(FROM_HERE, TimeDelta::FromSeconds(1),
424 this, &MyClass::DoStuff);
425 }
426 void StopDoingStuff() {
427 timer_.Stop();
428 }
429 private:
430 void DoStuff() {
431 // This method is called every second on the sequence that invoked
432 // StartDoingStuff().
433 }
434 base::RepeatingTimer timer_;
435};
436```
437
438## Cancelling a Task
439
440### Using base::WeakPtr
441
442[`base::WeakPtr`](https://cs.chromium.org/chromium/src/base/memory/weak_ptr.h)
443can be used to ensure that any callback bound to an object is canceled when that
444object is destroyed.
445
446```cpp
447int Compute() { … }
448
449class A {
450 public:
451 A() : weak_ptr_factory_(this) {}
452
453 void ComputeAndStore() {
454 // Schedule a call to Compute() in a thread pool followed by
455 // a call to A::Store() on the current sequence. The call to
456 // A::Store() is canceled when |weak_ptr_factory_| is destroyed.
457 // (guarantees that |this| will not be used-after-free).
458 base::PostTaskAndReplyWithResult(
459 FROM_HERE, base::BindOnce(&Compute),
460 base::BindOnce(&A::Store, weak_ptr_factory_.GetWeakPtr()));
461 }
462
463 private:
464 void Store(int value) { value_ = value; }
465
466 int value_;
467 base::WeakPtrFactory<A> weak_ptr_factory_;
468};
469```
470
471Note: `WeakPtr` is not thread-safe: `GetWeakPtr()`, `~WeakPtrFactory()`, and
472`Compute()` (bound to a `WeakPtr`) must all run on the same sequence.
473
474### Using base::CancelableTaskTracker
475
476[`base::CancelableTaskTracker`](https://cs.chromium.org/chromium/src/base/task/cancelable_task_tracker.h)
477allows cancellation to happen on a different sequence than the one on which
478tasks run. Keep in mind that `CancelableTaskTracker` cannot cancel tasks that
479have already started to run.
480
481```cpp
482auto task_runner = base::CreateTaskRunnerWithTraits(base::TaskTraits());
483base::CancelableTaskTracker cancelable_task_tracker;
484cancelable_task_tracker.PostTask(task_runner.get(), FROM_HERE,
485 base::Bind(&base::DoNothing));
486// Cancels Task(), only if it hasn't already started running.
487cancelable_task_tracker.TryCancelAll();
488```
489
490## Testing
491
492To test code that uses `base::ThreadTaskRunnerHandle`,
493`base::SequencedTaskRunnerHandle` or a function in
494[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h), instantiate a
495[`base::test::ScopedTaskEnvironment`](https://cs.chromium.org/chromium/src/base/test/scoped_task_environment.h)
496for the scope of the test.
497
498```cpp
499class MyTest : public testing::Test {
500 public:
501 // ...
502 protected:
503 base::test::ScopedTaskEnvironment scoped_task_environment_;
504};
505
506TEST(MyTest, MyTest) {
507 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&A));
508 base::SequencedTaskRunnerHandle::Get()->PostTask(FROM_HERE,
509 base::BindOnce(&B));
510 base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
511 FROM_HERE, base::BindOnce(&C), base::TimeDelta::Max());
512
513 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until it is empty.
514 // Delayed tasks are not added to the queue until they are ripe for execution.
515 base::RunLoop().RunUntilIdle();
516 // A and B have been executed. C is not ripe for execution yet.
517
518 base::RunLoop run_loop;
519 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&D));
520 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, run_loop.QuitClosure());
521 base::ThreadTaskRunnerHandle::Get()->PostTask(FROM_HERE, base::BindOnce(&E));
522
523 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until QuitClosure is
524 // invoked.
525 run_loop.Run();
526 // D and run_loop.QuitClosure() have been executed. E is still in the queue.
527
528 // Tasks posted to task scheduler run asynchronously as they are posted.
529 base::PostTaskWithTraits(FROM_HERE, base::TaskTraits(), base::BindOnce(&F));
530 auto task_runner =
531 base::CreateSequencedTaskRunnerWithTraits(base::TaskTraits());
532 task_runner->PostTask(FROM_HERE, base::BindOnce(&G));
533
534 // To block until all tasks posted to task scheduler are done running:
535 base::TaskScheduler::GetInstance()->FlushForTesting();
536 // F and G have been executed.
537
538 base::PostTaskWithTraitsAndReplyWithResult(
539 FROM_HERE, base::TaskTrait(),
540 base::BindOnce(&H), base::BindOnce(&I));
541
542 // This runs the (Thread|Sequenced)TaskRunnerHandle queue until both the
543 // (Thread|Sequenced)TaskRunnerHandle queue and the TaskSchedule queue are
544 // empty:
545 scoped_task_environment_.RunUntilIdle();
546 // E, H, I have been executed.
547}
548```
549
550## Legacy Post Task APIs
551
552The Chrome browser process has a few legacy named threads (aka
553BrowserThreads”). Each of these threads runs a specific type of task (e.g. the
554`FILE` thread handles low priority file operations, the `FILE_USER_BLOCKING`
555thread handles high priority file operations, the `CACHE` thread handles cache
556operations…). Usage of these named threads is now discouraged. New code should
557post tasks to task scheduler via
558[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h)
559instead.
560
561If for some reason you absolutely need to post a task to a legacy named thread
562(e.g. because it needs mutual exclusion with a task running on one of these
563threads), this is how you do it:
564
565```cpp
566content::BrowserThread::GetTaskRunnerForThread(content::BrowserThread::[IDENTIFIER])
567 ->PostTask(FROM_HERE, base::BindOnce(&Task));
568```
569
570Where `IDENTIFIER` is one of: `DB`, `FILE`, `FILE_USER_BLOCKING`, `PROCESS_LAUNCHER`, `CACHE`.
571
572The Chrome browser process has a blocking pool API:
573
574```cpp
575content::BrowserThread::PostBlockingPoolSequencedTask
576content::BrowserThread::GetBlockingPool
577```
578
579All tasks posted through this API are redirected to
580[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h).
581Therefore, there is no reason to add calls to this API.
582
583## Using TaskScheduler in a New Process
584
585TaskScheduler needs to be initialized in a process before the functions in
586[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h)
587can be used. Initialization of TaskScheduler in the Chrome browser process and
588child processes (renderer, GPU, utility) has already been taken care of. To use
589TaskScheduler in another process, initialize TaskScheduler early in the main
590function:
591
592```cpp
593// This initializes and starts TaskScheduler with default params.
594base::TaskScheduler::CreateAndStartWithDefaultParams(“process_name”);
595// The base/task_scheduler/post_task.h API can now be used. Tasks will be
596// scheduled as they are posted.
597
598// This initializes TaskScheduler.
599base::TaskScheduler::Create(“process_name”);
600// The base/task_scheduler/post_task.h API can now be used. No threads
601// will be created and no tasks will be scheduled until after Start() is called.
602base::TaskScheduler::GetInstance()->Start(params);
603// TaskScheduler can now create threads and schedule tasks.
604```
605
606And shutdown TaskScheduler late in the main function:
607
608```cpp
609base::TaskScheduler::GetInstance()->Shutdown();
610// Tasks posted with TaskShutdownBehavior::BLOCK_SHUTDOWN and
611// tasks posted with TaskShutdownBehavior::SKIP_ON_SHUTDOWN that
612// have started to run before the Shutdown() call have now completed their
613// execution. Tasks posted with
614// TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN may still be
615// running.
616```
Sebastien Marchandc95489b2017-05-25 16:39:34617## TaskRunner ownership
618
619TaskRunners shouldn't be passed through several components. Instead, the
620components that uses a TaskRunner should be the one that creates it.
621
622See [this example](https://codereview.chromium.org/2885173002/) of a
623refactoring where a TaskRunner was passed through a lot of components only to be
624used in an eventual leaf. The leaf can and should now obtain its TaskRunner
625directly from
626[`base/task_scheduler/post_task.h`](https://cs.chromium.org/chromium/src/base/task_scheduler/post_task.h).