1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146
|
// 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 <utility>
#include "base/functional/bind.h"
#include "base/task/default_delayed_task_handle_delegate.h"
#include "base/task/thread_pool/thread_pool_instance.h"
#include "base/time/time.h"
namespace base {
namespace {
constinit thread_local SequencedTaskRunner::CurrentDefaultHandle*
current_default_handle = nullptr;
} // 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<DefaultDelayedTaskHandleDelegate>();
task = delayed_task_handle_delegate->BindCallback(std::move(task));
DelayedTaskHandle delayed_task_handle(
std::move(delayed_task_handle_delegate));
PostDelayedTask(from_here, std::move(task), delay);
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<DefaultDelayedTaskHandleDelegate>();
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());
}
bool SequencedTaskRunner::RunOrPostTask(subtle::RunOrPostTaskPassKey,
const Location& from_here,
OnceClosure task) {
return PostTask(from_here, std::move(task));
}
// static
const scoped_refptr<SequencedTaskRunner>&
SequencedTaskRunner::GetCurrentDefault() {
CHECK(HasCurrentDefault())
<< "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_handle->task_runner_;
}
// static
bool SequencedTaskRunner::HasCurrentDefault() {
return !!current_default_handle && !!current_default_handle->task_runner_;
}
SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
scoped_refptr<SequencedTaskRunner> task_runner)
: CurrentDefaultHandle(std::move(task_runner), MayAlreadyExist{}) {
CHECK(!previous_handle_ || !previous_handle_->task_runner_);
}
SequencedTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() {
DCHECK_EQ(current_default_handle, this);
current_default_handle = previous_handle_;
}
SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
scoped_refptr<SequencedTaskRunner> task_runner,
MayAlreadyExist)
: task_runner_(std::move(task_runner)),
previous_handle_(current_default_handle) {
// Support overriding the current default with a null task runner or a task
// runner that runs its tasks in the current sequence.
DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence());
current_default_handle = this;
}
bool SequencedTaskRunner::DeleteOrReleaseSoonInternal(
const Location& from_here,
void (*deleter)(const void*),
const void* object) {
// Allow memory to leak on shutdown. ScopedFizzleBlockShutdownTasks avoids a
// DCHECK about posting a task to a potentially BLOCK_SHUTDOWN task runner
// after shut down in cleanups that happen as things are reaped in the final
// phases of shutdown (ref. crbug.com/420259698; and other instances).
ThreadPoolInstance::ScopedFizzleBlockShutdownTasks fizzler;
return PostNonNestableTask(from_here, BindOnce(deleter, object));
}
OnTaskRunnerDeleter::OnTaskRunnerDeleter(
scoped_refptr<SequencedTaskRunner> task_runner)
: task_runner_(std::move(task_runner)) {}
OnTaskRunnerDeleter::~OnTaskRunnerDeleter() = default;
OnTaskRunnerDeleter::OnTaskRunnerDeleter(OnTaskRunnerDeleter&&) = default;
OnTaskRunnerDeleter& OnTaskRunnerDeleter::operator=(OnTaskRunnerDeleter&&) =
default;
} // namespace base
|