| Index: base/threading/task_runner_handle.cc
|
| diff --git a/base/threading/task_runner_handle.cc b/base/threading/task_runner_handle.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..c32a5f679758ab68909ff0d46cdb0002a30afb26
|
| --- /dev/null
|
| +++ b/base/threading/task_runner_handle.cc
|
| @@ -0,0 +1,139 @@
|
| +// Copyright 2016 The Chromium Authors. All rights reserved.
|
| +// Use of this source code is governed by a BSD-style license that can be
|
| +// found in the LICENSE file.
|
| +
|
| +#include "base/threading/task_runner_handle.h"
|
| +
|
| +#include <utility>
|
| +
|
| +#include "base/lazy_instance.h"
|
| +#include "base/logging.h"
|
| +#include "base/threading/sequenced_worker_pool.h"
|
| +#include "base/threading/thread_local.h"
|
| +
|
| +namespace base {
|
| +
|
| +namespace {
|
| +
|
| +// TaskScopeState for the current thread stored in TLS.
|
| +LazyInstance<ThreadLocalPointer<internal::TaskScopeState>>::Leaky
|
| + g_task_scope_state = LAZY_INSTANCE_INITIALIZER;
|
| +
|
| +} // namespace
|
| +
|
| +scoped_refptr<TaskRunner> TaskRunnerHandle::Get() {
|
| + DCHECK(HasTaskScope());
|
| +
|
| + const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
|
| + if (state)
|
| + return state->task_runner;
|
| +
|
| + // Explicitly support the SequencedWorkerPool here while it still exists
|
| + // (supporting TaskRunnerHandles from it would be non-trivial and it will soon
|
| + // be deprecated in favor of TaskScheduler).
|
| + return SequencedWorkerPool::GetWorkerPoolForCurrentThread();
|
| +}
|
| +
|
| +scoped_refptr<SequencedTaskRunner> TaskRunnerHandle::GetSequenced() {
|
| + DCHECK(HasSequencedTaskScope());
|
| +
|
| + const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
|
| + if (state) {
|
| + return scoped_refptr<SequencedTaskRunner>(
|
| + static_cast<SequencedTaskRunner*>(state->task_runner.get()));
|
| + }
|
| +
|
| + // Assuming there is a sequenced scope and it isn't in our TLS, the current
|
| + // context is the SequencedWorkerPool: get its SequencedTaskRunner. Note: this
|
| + // special case will go away when SequencedWorkerPool is deprecated in favor
|
| + // of TaskScheduler.
|
| + scoped_refptr<SequencedTaskRunner> sequenced_worker_pool_runner =
|
| + SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread();
|
| + return sequenced_worker_pool_runner;
|
| +}
|
| +
|
| +scoped_refptr<SingleThreadTaskRunner> TaskRunnerHandle::GetSingleThreaded() {
|
| + DCHECK(HasSingleThreadTaskScope());
|
| + return scoped_refptr<SingleThreadTaskRunner>(
|
| + static_cast<SingleThreadTaskRunner*>(
|
| + g_task_scope_state.Get().Get()->task_runner.get()));
|
| +}
|
| +
|
| +bool TaskRunnerHandle::HasTaskScope() {
|
| + return g_task_scope_state.Get().Get() ||
|
| + SequencedWorkerPool::GetWorkerPoolForCurrentThread();
|
| +}
|
| +
|
| +bool TaskRunnerHandle::HasSequencedTaskScope() {
|
| + // TODO(gab): Replace GetWorkerPoolForCurrentThread() below with
|
| + // GetSequenceTokenForCurrentThread() once returning a SequencedTaskRunner
|
| + // from an unsequenced task is deprecated.
|
| + const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
|
| + return state ? state->type >= internal::TaskScopeState::SEQUENCED
|
| + : !!SequencedWorkerPool::GetWorkerPoolForCurrentThread();
|
| +}
|
| +
|
| +bool TaskRunnerHandle::HasSingleThreadTaskScope() {
|
| + const internal::TaskScopeState* state = g_task_scope_state.Get().Get();
|
| + return (state && state->type >= internal::TaskScopeState::SINGLE_THREADED);
|
| +}
|
| +
|
| +TaskRunnerHandle::TaskScope::TaskScope(scoped_refptr<TaskRunner> task_runner)
|
| + : state_(std::move(task_runner)) {}
|
| +
|
| +TaskRunnerHandle::SequencedTaskScope::SequencedTaskScope(
|
| + scoped_refptr<SequencedTaskRunner> sequenced_task_runner)
|
| + : state_(std::move(sequenced_task_runner)) {}
|
| +
|
| +TaskRunnerHandle::SingleThreadTaskScope::SingleThreadTaskScope(
|
| + scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner)
|
| + : state_(std::move(single_thread_task_runner)) {}
|
| +
|
| +namespace internal {
|
| +
|
| +TaskScopeState::TaskScopeState(scoped_refptr<TaskRunner> task_runner_in)
|
| + : type(PARALLEL), task_runner(std::move(task_runner_in)) {
|
| + DCHECK(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + DCHECK(!TaskRunnerHandle::HasTaskScope());
|
| + g_task_scope_state.Get().Set(this);
|
| + DCHECK(TaskRunnerHandle::HasTaskScope());
|
| +}
|
| +
|
| +TaskScopeState::TaskScopeState(
|
| + scoped_refptr<SequencedTaskRunner> sequenced_task_runner_in)
|
| + : type(SEQUENCED), task_runner(std::move(sequenced_task_runner_in)) {
|
| + DCHECK(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + DCHECK(!TaskRunnerHandle::HasTaskScope());
|
| + g_task_scope_state.Get().Set(this);
|
| + DCHECK(TaskRunnerHandle::HasSequencedTaskScope());
|
| +}
|
| +
|
| +TaskScopeState::TaskScopeState(
|
| + scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner_in)
|
| + : type(SINGLE_THREADED),
|
| + task_runner(std::move(single_thread_task_runner_in)) {
|
| + DCHECK(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + DCHECK(!TaskRunnerHandle::HasTaskScope());
|
| + g_task_scope_state.Get().Set(this);
|
| + DCHECK(TaskRunnerHandle::HasSingleThreadTaskScope());
|
| +}
|
| +
|
| +TaskScopeState::~TaskScopeState() {
|
| + DCHECK(task_runner->RunsTasksOnCurrentThread());
|
| +
|
| + DCHECK_EQ(task_runner, TaskRunnerHandle::Get());
|
| +
|
| + DCHECK(TaskRunnerHandle::HasTaskScope());
|
| + DCHECK(TaskRunnerHandle::HasSequencedTaskScope() || type < SEQUENCED);
|
| + DCHECK(TaskRunnerHandle::HasSingleThreadTaskScope() ||
|
| + type < SINGLE_THREADED);
|
| + g_task_scope_state.Get().Set(nullptr);
|
| + DCHECK(!TaskRunnerHandle::HasTaskScope());
|
| +}
|
| +
|
| +} // namespace internal
|
| +
|
| +} // namespace base
|
|
|