// Copyright 2012 The Chromium Authors // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. #include "base/task/sequenced_task_runner.h" #include #include "base/bind.h" #include "base/no_destructor.h" #include "base/task/default_delayed_task_handle_delegate.h" #include "base/threading/thread_local.h" #include "base/time/time.h" namespace base { namespace { ThreadLocalPointer& CurrentDefaultHandleTls() { static NoDestructor< ThreadLocalPointer> instance; return *instance; } } // namespace bool SequencedTaskRunner::PostNonNestableTask(const Location& from_here, OnceClosure task) { return PostNonNestableDelayedTask(from_here, std::move(task), base::TimeDelta()); } DelayedTaskHandle SequencedTaskRunner::PostCancelableDelayedTask( subtle::PostDelayedTaskPassKey, const Location& from_here, OnceClosure task, TimeDelta delay) { auto delayed_task_handle_delegate = std::make_unique(); task = delayed_task_handle_delegate->BindCallback(std::move(task)); DelayedTaskHandle delayed_task_handle( std::move(delayed_task_handle_delegate)); // If the task fails to be posted, the handle will automatically be // invalidated upon destruction of the callback object. if (!PostDelayedTask(from_here, std::move(task), delay)) DCHECK(!delayed_task_handle.IsValid()); return delayed_task_handle; } DelayedTaskHandle SequencedTaskRunner::PostCancelableDelayedTaskAt( subtle::PostDelayedTaskPassKey pass_key, const Location& from_here, OnceClosure task, TimeTicks delayed_run_time, subtle::DelayPolicy deadline_policy) { auto delayed_task_handle_delegate = std::make_unique(); task = delayed_task_handle_delegate->BindCallback(std::move(task)); DelayedTaskHandle delayed_task_handle( std::move(delayed_task_handle_delegate)); if (!PostDelayedTaskAt(pass_key, from_here, std::move(task), delayed_run_time, deadline_policy)) { DCHECK(!delayed_task_handle.IsValid()); } return delayed_task_handle; } bool SequencedTaskRunner::PostDelayedTaskAt( subtle::PostDelayedTaskPassKey, const Location& from_here, OnceClosure task, TimeTicks delayed_run_time, subtle::DelayPolicy deadline_policy) { return PostDelayedTask(from_here, std::move(task), delayed_run_time.is_null() ? base::TimeDelta() : delayed_run_time - TimeTicks::Now()); } // static const scoped_refptr& SequencedTaskRunner::GetCurrentDefault() { const CurrentDefaultHandle* current_default = CurrentDefaultHandleTls().Get(); CHECK(current_default) << "Error: This caller requires a sequenced context (i.e. the current " "task needs to run from a SequencedTaskRunner). If you're in a test " "refer to //docs/threading_and_tasks_testing.md."; return current_default->task_runner_; } // static bool SequencedTaskRunner::HasCurrentDefault() { return !!CurrentDefaultHandleTls().Get(); } SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle( scoped_refptr task_runner) : task_runner_(std::move(task_runner)) { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK(!SequencedTaskRunner::HasCurrentDefault()); CurrentDefaultHandleTls().Set(this); } SequencedTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() { DCHECK(task_runner_->RunsTasksInCurrentSequence()); DCHECK_EQ(CurrentDefaultHandleTls().Get(), this); CurrentDefaultHandleTls().Set(nullptr); } bool SequencedTaskRunner::DeleteOrReleaseSoonInternal( const Location& from_here, void (*deleter)(const void*), const void* object) { return PostNonNestableTask(from_here, BindOnce(deleter, object)); } OnTaskRunnerDeleter::OnTaskRunnerDeleter( scoped_refptr task_runner) : task_runner_(std::move(task_runner)) { } OnTaskRunnerDeleter::~OnTaskRunnerDeleter() = default; OnTaskRunnerDeleter::OnTaskRunnerDeleter(OnTaskRunnerDeleter&&) = default; OnTaskRunnerDeleter& OnTaskRunnerDeleter::operator=( OnTaskRunnerDeleter&&) = default; } // namespace base