| OLD | NEW |
| (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_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 scoped_refptr<SequencedTaskRunner>( |
| 43 static_cast<SequencedTaskRunner*>(state->task_runner.get())); |
| 44 } |
| 45 |
| 46 // Assuming there is a sequenced scope and it isn't in our TLS, the current |
| 47 // context is the SequencedWorkerPool: get its SequencedTaskRunner. Note: this |
| 48 // special case will go away when SequencedWorkerPool is deprecated in favor |
| 49 // of TaskScheduler. |
| 50 scoped_refptr<SequencedTaskRunner> sequenced_worker_pool_runner = |
| 51 SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread(); |
| 52 return sequenced_worker_pool_runner; |
| 53 } |
| 54 |
| 55 scoped_refptr<SingleThreadTaskRunner> TaskRunnerHandle::GetSingleThreaded() { |
| 56 DCHECK(HasSingleThreadTaskScope()); |
| 57 return scoped_refptr<SingleThreadTaskRunner>( |
| 58 static_cast<SingleThreadTaskRunner*>( |
| 59 g_task_scope_state.Get().Get()->task_runner.get())); |
| 60 } |
| 61 |
| 62 bool TaskRunnerHandle::HasTaskScope() { |
| 63 return g_task_scope_state.Get().Get() || |
| 64 SequencedWorkerPool::GetWorkerPoolForCurrentThread(); |
| 65 } |
| 66 |
| 67 bool TaskRunnerHandle::HasSequencedTaskScope() { |
| 68 // TODO(gab): Replace GetWorkerPoolForCurrentThread() below with |
| 69 // GetSequenceTokenForCurrentThread() once returning a SequencedTaskRunner |
| 70 // from an unsequenced task is deprecated. |
| 71 const internal::TaskScopeState* state = g_task_scope_state.Get().Get(); |
| 72 return state ? state->type >= internal::TaskScopeState::SEQUENCED |
| 73 : !!SequencedWorkerPool::GetWorkerPoolForCurrentThread(); |
| 74 } |
| 75 |
| 76 bool TaskRunnerHandle::HasSingleThreadTaskScope() { |
| 77 const internal::TaskScopeState* state = g_task_scope_state.Get().Get(); |
| 78 return (state && state->type >= internal::TaskScopeState::SINGLE_THREADED); |
| 79 } |
| 80 |
| 81 TaskRunnerHandle::TaskScope::TaskScope(scoped_refptr<TaskRunner> task_runner) |
| 82 : state_(std::move(task_runner)) {} |
| 83 |
| 84 TaskRunnerHandle::SequencedTaskScope::SequencedTaskScope( |
| 85 scoped_refptr<SequencedTaskRunner> sequenced_task_runner) |
| 86 : state_(std::move(sequenced_task_runner)) {} |
| 87 |
| 88 TaskRunnerHandle::SingleThreadTaskScope::SingleThreadTaskScope( |
| 89 scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner) |
| 90 : state_(std::move(single_thread_task_runner)) {} |
| 91 |
| 92 namespace internal { |
| 93 |
| 94 TaskScopeState::TaskScopeState(scoped_refptr<TaskRunner> task_runner_in) |
| 95 : type(PARALLEL), task_runner(std::move(task_runner_in)) { |
| 96 DCHECK(task_runner->RunsTasksOnCurrentThread()); |
| 97 |
| 98 DCHECK(!TaskRunnerHandle::HasTaskScope()); |
| 99 g_task_scope_state.Get().Set(this); |
| 100 DCHECK(TaskRunnerHandle::HasTaskScope()); |
| 101 } |
| 102 |
| 103 TaskScopeState::TaskScopeState( |
| 104 scoped_refptr<SequencedTaskRunner> sequenced_task_runner_in) |
| 105 : type(SEQUENCED), task_runner(std::move(sequenced_task_runner_in)) { |
| 106 DCHECK(task_runner->RunsTasksOnCurrentThread()); |
| 107 |
| 108 DCHECK(!TaskRunnerHandle::HasTaskScope()); |
| 109 g_task_scope_state.Get().Set(this); |
| 110 DCHECK(TaskRunnerHandle::HasSequencedTaskScope()); |
| 111 } |
| 112 |
| 113 TaskScopeState::TaskScopeState( |
| 114 scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner_in) |
| 115 : type(SINGLE_THREADED), |
| 116 task_runner(std::move(single_thread_task_runner_in)) { |
| 117 DCHECK(task_runner->RunsTasksOnCurrentThread()); |
| 118 |
| 119 DCHECK(!TaskRunnerHandle::HasTaskScope()); |
| 120 g_task_scope_state.Get().Set(this); |
| 121 DCHECK(TaskRunnerHandle::HasSingleThreadTaskScope()); |
| 122 } |
| 123 |
| 124 TaskScopeState::~TaskScopeState() { |
| 125 DCHECK(task_runner->RunsTasksOnCurrentThread()); |
| 126 |
| 127 DCHECK_EQ(task_runner, TaskRunnerHandle::Get()); |
| 128 |
| 129 DCHECK(TaskRunnerHandle::HasTaskScope()); |
| 130 DCHECK(TaskRunnerHandle::HasSequencedTaskScope() || type < SEQUENCED); |
| 131 DCHECK(TaskRunnerHandle::HasSingleThreadTaskScope() || |
| 132 type < SINGLE_THREADED); |
| 133 g_task_scope_state.Get().Set(nullptr); |
| 134 DCHECK(!TaskRunnerHandle::HasTaskScope()); |
| 135 } |
| 136 |
| 137 } // namespace internal |
| 138 |
| 139 } // namespace base |
| OLD | NEW |