// 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