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

Side by Side Diff: base/threading/task_runner_handle.cc

Issue 2042383004: Introduce TaskRunnerHandle. (Closed) Base URL: https://chromium.googlesource.com/chromium/src.git@master
Patch Set: support for parallel tasks from SequencedWorkerPool Created 4 years, 6 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 unified diff | Download patch
OLDNEW
(Empty)
1 // Copyright 2016 The Chromium Authors. All rights reserved.
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/threading/task_runner_handle.h"
6
7 #include <utility>
8
9 #include "base/lazy_instance.h"
10 #include "base/logging.h"
11 #include "base/threading/sequenced_worker_pool.h"
12 #include "base/threading/thread_local.h"
13
14 namespace base {
15
16 namespace {
17
18 // TaskScopeState for the current thread stored in TLS.
19 LazyInstance<ThreadLocalPointer<internal::TaskScopeState>>::Leaky
20 g_task_scope_state = LAZY_INSTANCE_INITIALIZER;
21
22 } // namespace
23
24 scoped_refptr<TaskRunner> TaskRunnerHandle::Get() {
25 DCHECK(HasTaskScope());
26
27 const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
28 if (state)
29 return state->task_runners.task_runner;
30
31 // Explicitly support the SequencedWorkerPool here while it still exists
32 // (supporting TaskRunnerHandles from it would be non-trivial and it will soon
33 // be deprecated in favor of TaskScheduler).
34 return SequencedWorkerPool::GetWorkerPoolForCurrentThread();
35 }
36
37 scoped_refptr<SequencedTaskRunner> TaskRunnerHandle::GetSequenced() {
38 DCHECK(HasSequencedTaskScope());
39
40 const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
41 if (state)
42 return state->task_runners.sequenced_task_runner;
43
44 // Assuming there is a sequenced scope and it isn't in our TLS, the current
45 // context is the SequencedWorkerPool: get its SequencedTaskRunner. Note: this
46 // special case will go away when SequencedWorkerPool is deprecated in favor
47 // of TaskScheduler.
48 scoped_refptr<SequencedTaskRunner> sequenced_worker_pool_runner =
49 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
50 return sequenced_worker_pool_runner;
51 }
52
53 scoped_refptr<SingleThreadTaskRunner> TaskRunnerHandle::GetSingleThreaded() {
54 DCHECK(HasSingleThreadTaskScope());
55 return g_task_scope_state.Get().Get()->task_runners.single_thread_task_runner;
56 }
57
58 bool TaskRunnerHandle::HasTaskScope() {
59 return g_task_scope_state.Get().Get() ||
60 SequencedWorkerPool::GetWorkerPoolForCurrentThread();
61 }
62
63 bool TaskRunnerHandle::HasSequencedTaskScope() {
64 // TODO(gab): Replace GetWorkerPoolForCurrentThread() below with
65 // GetSequenceTokenForCurrentThread() once returning a SequencedTaskRunner
66 // from an unsequenced task is deprecated.
67 const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
68 return state ? state->type >= internal::TaskScopeState::SEQUENCED
69 : !!SequencedWorkerPool::GetWorkerPoolForCurrentThread();
70 }
71
72 bool TaskRunnerHandle::HasSingleThreadTaskScope() {
73 const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
74 return (state && state->type >= internal::TaskScopeState::SINGLE_THREADED);
75 }
76
77 TaskRunnerHandle::TaskScope::TaskScope(scoped_refptr<TaskRunner> task_runner)
78 : state_(std::move(task_runner)) {}
79
80 TaskRunnerHandle::SequencedTaskScope::SequencedTaskScope(
81 scoped_refptr<SequencedTaskRunner> sequenced_task_runner)
82 : state_(std::move(sequenced_task_runner)) {}
83
84 TaskRunnerHandle::SingleThreadTaskScope::SingleThreadTaskScope(
85 scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner)
86 : state_(std::move(single_thread_task_runner)) {}
87
88 namespace internal {
89
90 TaskScopeState::TaskScopeState(scoped_refptr<TaskRunner> task_runner)
91 : type(PARALLEL), task_runners(std::move(task_runner)) {
92 DCHECK(!TaskRunnerHandle::HasTaskScope());
93 g_task_scope_state.Get().Set(this);
94 }
95
96 TaskScopeState::TaskScopeState(
97 scoped_refptr<SequencedTaskRunner> sequenced_task_runner)
98 : type(SEQUENCED), task_runners(std::move(sequenced_task_runner)) {
99 DCHECK(!TaskRunnerHandle::HasTaskScope());
100 g_task_scope_state.Get().Set(this);
101 }
102
103 TaskScopeState::TaskScopeState(
104 scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner)
105 : type(SINGLE_THREADED),
106 task_runners(std::move(single_thread_task_runner)) {
107 DCHECK(!TaskRunnerHandle::HasTaskScope());
108 g_task_scope_state.Get().Set(this);
109 }
110
111 TaskScopeState::~TaskScopeState() {
112 DCHECK(TaskRunnerHandle::HasTaskScope());
113 DCHECK(TaskRunnerHandle::HasSequencedTaskScope() || type < SEQUENCED);
114 DCHECK(TaskRunnerHandle::HasSingleThreadTaskScope() ||
115 type < SINGLE_THREADED);
116
117 DCHECK(TaskRunnerHandle::Get()->RunsTasksOnCurrentThread());
118
119 g_task_scope_state.Get().Set(nullptr);
120 DCHECK(!TaskRunnerHandle::HasTaskScope());
121 }
122
123 TaskScopeState::TaskRunnerUnion::TaskRunnerUnion(
124 scoped_refptr<TaskRunner> task_runner_in)
125 : task_runner(std::move(task_runner_in)) {
126 DCHECK(task_runner->RunsTasksOnCurrentThread());
127 }
128
129 TaskScopeState::TaskRunnerUnion::TaskRunnerUnion(
130 scoped_refptr<SequencedTaskRunner> sequenced_task_runner_in)
131 : sequenced_task_runner(std::move(sequenced_task_runner_in)) {
132 DCHECK(sequenced_task_runner->RunsTasksOnCurrentThread());
133 }
134
135 TaskScopeState::TaskRunnerUnion::TaskRunnerUnion(
136 scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner_in)
137 : single_thread_task_runner(std::move(single_thread_task_runner_in)) {
138 DCHECK(single_thread_task_runner->BelongsToCurrentThread());
139 }
140
141 TaskScopeState::TaskRunnerUnion::~TaskRunnerUnion() {
142 // Unions with complex members require explicit destruction. All types in the
143 // union derive from base::TaskRunner, as such it is ok to always use that
144 // type for deletion.
145 if (task_runner)
146 task_runner.get()->Release();
fdoray 2016/06/17 14:29:02 I'm not strongly against the union, but with a cas
gab 2016/06/20 19:55:36 Right, done (based on what I read in this I think
147 }
148
149 } // namespace internal
150
151 } // namespace base
OLDNEW

Powered by Google App Engine
This is Rietveld 408576698