| // Copyright 2015 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/sequenced_task_runner_handle.h" | |
| #include <utility> | |
| #include "base/lazy_instance.h" | |
| #include "base/logging.h" | |
| #include "base/threading/thread_local.h" | |
| #include "base/threading/thread_task_runner_handle.h" | |
| namespace base { | |
| namespace { | |
| LazyInstance<ThreadLocalPointer<SequencedTaskRunnerHandle>>::Leaky | |
| sequenced_task_runner_tls = LAZY_INSTANCE_INITIALIZER; | |
| } // namespace | |
| // static | |
| scoped_refptr<SequencedTaskRunner> SequencedTaskRunnerHandle::Get() { | |
| // Return the registered SequencedTaskRunner, if any. | |
| const SequencedTaskRunnerHandle* handle = | |
| sequenced_task_runner_tls.Pointer()->Get(); | |
| if (handle) | |
| return handle->task_runner_; | |
| // Note if you hit this: the problem is the lack of a sequenced context. The | |
| // ThreadTaskRunnerHandle is just the last attempt at finding such a context. | |
| CHECK(ThreadTaskRunnerHandle::IsSet()) | |
| << "Error: This caller requires a sequenced context (i.e. the " | |
| "current task needs to run from a SequencedTaskRunner)."; | |
| return ThreadTaskRunnerHandle::Get(); | |
| } | |
| // static | |
| bool SequencedTaskRunnerHandle::IsSet() { | |
| return sequenced_task_runner_tls.Pointer()->Get() || | |
| ThreadTaskRunnerHandle::IsSet(); | |
| } | |
| SequencedTaskRunnerHandle::SequencedTaskRunnerHandle( | |
| scoped_refptr<SequencedTaskRunner> task_runner) | |
| : task_runner_(std::move(task_runner)) { | |
| DCHECK(task_runner_->RunsTasksInCurrentSequence()); | |
| DCHECK(!SequencedTaskRunnerHandle::IsSet()); | |
| sequenced_task_runner_tls.Pointer()->Set(this); | |
| } | |
| SequencedTaskRunnerHandle::~SequencedTaskRunnerHandle() { | |
| DCHECK(task_runner_->RunsTasksInCurrentSequence()); | |
| DCHECK_EQ(sequenced_task_runner_tls.Pointer()->Get(), this); | |
| sequenced_task_runner_tls.Pointer()->Set(nullptr); | |
| } | |
| } // namespace base |