Chromium Code Reviews| 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..3a29ab5b222921cc86a10e867487ae34edffe06c |
| --- /dev/null |
| +++ b/base/threading/task_runner_handle.cc |
| @@ -0,0 +1,130 @@ |
| +// 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/sequenced_task_runner.h" |
| +#include "base/single_thread_task_runner.h" |
| +#include "base/task_runner.h" |
| +#include "base/threading/sequenced_worker_pool.h" |
| +#include "base/threading/thread_local.h" |
| + |
| +namespace base { |
| + |
| +namespace { |
| + |
| +// Thread-local TaskScopes, at most one of these should be set at a time on any |
| +// given thread. |
| +LazyInstance<ThreadLocalPointer<TaskRunnerHandle::TaskScope>>::Leaky |
| + task_scope_tls = LAZY_INSTANCE_INITIALIZER; |
| +LazyInstance<ThreadLocalPointer<TaskRunnerHandle::SequencedTaskScope>>::Leaky |
| + sequenced_task_scope_tls = LAZY_INSTANCE_INITIALIZER; |
| +LazyInstance<ThreadLocalPointer<TaskRunnerHandle::SingleThreadTaskScope>>::Leaky |
| + single_thread_task_scope_tls = LAZY_INSTANCE_INITIALIZER; |
| + |
| +} // namespace |
| + |
| +scoped_refptr<TaskRunner> TaskRunnerHandle::Get() { |
| + DCHECK(HasTaskScope()); |
| + |
| + if (single_thread_task_scope_tls.Pointer()->Get()) { |
|
fdoray
2016/06/08 18:10:44
if (HasSingleThreadTaskScope())
return GetSingle
gab
2016/06/08 20:29:19
That feels inconsistent (because it wouldn't be op
|
| + return single_thread_task_scope_tls.Pointer() |
| + ->Get() |
| + ->single_thread_task_runner_; |
| + } else if (sequenced_task_scope_tls.Pointer()->Get()) { |
| + return sequenced_task_scope_tls.Pointer()->Get()->sequenced_task_runner_; |
| + } |
| + return task_scope_tls.Pointer()->Get()->task_runner_; |
| +} |
| + |
| +scoped_refptr<SequencedTaskRunner> TaskRunnerHandle::GetSequenced() { |
| + DCHECK(HasSequencedTaskScope()); |
| + |
| + if (single_thread_task_scope_tls.Pointer()->Get()) { |
| + return single_thread_task_scope_tls.Pointer() |
| + ->Get() |
| + ->single_thread_task_runner_; |
| + } else if (sequenced_task_scope_tls.Pointer()->Get()) { |
| + return sequenced_task_scope_tls.Pointer()->Get()->sequenced_task_runner_; |
| + } |
| + |
| + // As a last resort, attempt to return the SequencedWorkerPool's |
| + // SequencedTaskRunner, if that's the current context. |
| + // TODO(gab): Remove this when SequencedWorkerPool is deprecated in favor of |
| + // TaskScheduler. |
| + scoped_refptr<base::SequencedTaskRunner> task_runner = |
| + SequencedWorkerPool::GetSequencedTaskRunnerForCurrentThread(); |
| + return task_runner; |
| +} |
| + |
| +scoped_refptr<SingleThreadTaskRunner> TaskRunnerHandle::GetSingleThreaded() { |
| + DCHECK(HasSingleThreadTaskScope()); |
| + return single_thread_task_scope_tls.Pointer() |
| + ->Get() |
| + ->single_thread_task_runner_; |
| +} |
| + |
| +bool TaskRunnerHandle::HasTaskScope() { |
| + return task_scope_tls.Pointer()->Get() || HasSequencedTaskScope(); |
| +} |
| + |
| +bool TaskRunnerHandle::HasSequencedTaskScope() { |
| + return sequenced_task_scope_tls.Pointer()->Get() || |
| + SequencedWorkerPool::GetWorkerPoolForCurrentThread() || |
| + HasSingleThreadTaskScope(); |
| +} |
| + |
| +bool TaskRunnerHandle::HasSingleThreadTaskScope() { |
| + return !!single_thread_task_scope_tls.Pointer()->Get(); |
| +} |
| + |
| +TaskRunnerHandle::TaskScope::TaskScope(scoped_refptr<TaskRunner> task_runner) |
| + : task_runner_(std::move(task_runner)) { |
| + DCHECK(task_runner_->RunsTasksOnCurrentThread()); |
| + DCHECK(!HasTaskScope()); |
| + task_scope_tls.Pointer()->Set(this); |
| +} |
| + |
| +TaskRunnerHandle::TaskScope::~TaskScope() { |
| + DCHECK(HasTaskScope()); |
| + DCHECK(Get()->RunsTasksOnCurrentThread()); |
| + task_scope_tls.Pointer()->Set(nullptr); |
| + DCHECK(!HasTaskScope()); |
| +} |
| + |
| +TaskRunnerHandle::SequencedTaskScope::SequencedTaskScope( |
| + scoped_refptr<SequencedTaskRunner> sequenced_task_runner) |
| + : sequenced_task_runner_(std::move(sequenced_task_runner)) { |
| + DCHECK(sequenced_task_runner_->RunsTasksOnCurrentThread()); |
| + DCHECK(!HasTaskScope()); |
| + sequenced_task_scope_tls.Pointer()->Set(this); |
| +} |
| + |
| +TaskRunnerHandle::SequencedTaskScope::~SequencedTaskScope() { |
| + DCHECK(HasSequencedTaskScope()); |
| + DCHECK(GetSequenced()->RunsTasksOnCurrentThread()); |
| + sequenced_task_scope_tls.Pointer()->Set(nullptr); |
| + DCHECK(!HasTaskScope()); |
| +} |
| + |
| +TaskRunnerHandle::SingleThreadTaskScope::SingleThreadTaskScope( |
| + scoped_refptr<SingleThreadTaskRunner> single_thread_task_runner) |
| + : single_thread_task_runner_(std::move(single_thread_task_runner)) { |
| + DCHECK(single_thread_task_runner_->BelongsToCurrentThread()); |
| + DCHECK(!HasTaskScope()); |
| + single_thread_task_scope_tls.Pointer()->Set(this); |
| +} |
| + |
| +TaskRunnerHandle::SingleThreadTaskScope::~SingleThreadTaskScope() { |
| + DCHECK(HasSingleThreadTaskScope()); |
| + DCHECK(GetSingleThreaded()->BelongsToCurrentThread()); |
| + single_thread_task_scope_tls.Pointer()->Set(nullptr); |
| + DCHECK(!HasTaskScope()); |
| +} |
| + |
| +} // namespace base |