1 // Copyright 2012 The Chromium Authors
2 // Use of this source code is governed by a BSD-style license that can be
3 // found in the LICENSE file.
4
5 #include "base/task/sequenced_task_runner.h"
6
7 #include <utility>
8
9 #include "base/functional/bind.h"
10 #include "base/task/default_delayed_task_handle_delegate.h"
11 #include "base/time/time.h"
12
13 namespace base {
14
15 namespace {
16
17 constinit thread_local SequencedTaskRunner::CurrentDefaultHandle*
18 current_default_handle = nullptr;
19
20 } // namespace
21
PostNonNestableTask(const Location & from_here,OnceClosure task)22 bool SequencedTaskRunner::PostNonNestableTask(const Location& from_here,
23 OnceClosure task) {
24 return PostNonNestableDelayedTask(from_here, std::move(task),
25 base::TimeDelta());
26 }
27
PostCancelableDelayedTask(subtle::PostDelayedTaskPassKey,const Location & from_here,OnceClosure task,TimeDelta delay)28 DelayedTaskHandle SequencedTaskRunner::PostCancelableDelayedTask(
29 subtle::PostDelayedTaskPassKey,
30 const Location& from_here,
31 OnceClosure task,
32 TimeDelta delay) {
33 auto delayed_task_handle_delegate =
34 std::make_unique<DefaultDelayedTaskHandleDelegate>();
35
36 task = delayed_task_handle_delegate->BindCallback(std::move(task));
37
38 DelayedTaskHandle delayed_task_handle(
39 std::move(delayed_task_handle_delegate));
40
41 PostDelayedTask(from_here, std::move(task), delay);
42
43 return delayed_task_handle;
44 }
45
PostCancelableDelayedTaskAt(subtle::PostDelayedTaskPassKey pass_key,const Location & from_here,OnceClosure task,TimeTicks delayed_run_time,subtle::DelayPolicy deadline_policy)46 DelayedTaskHandle SequencedTaskRunner::PostCancelableDelayedTaskAt(
47 subtle::PostDelayedTaskPassKey pass_key,
48 const Location& from_here,
49 OnceClosure task,
50 TimeTicks delayed_run_time,
51 subtle::DelayPolicy deadline_policy) {
52 auto delayed_task_handle_delegate =
53 std::make_unique<DefaultDelayedTaskHandleDelegate>();
54
55 task = delayed_task_handle_delegate->BindCallback(std::move(task));
56
57 DelayedTaskHandle delayed_task_handle(
58 std::move(delayed_task_handle_delegate));
59
60 if (!PostDelayedTaskAt(pass_key, from_here, std::move(task), delayed_run_time,
61 deadline_policy)) {
62 DCHECK(!delayed_task_handle.IsValid());
63 }
64 return delayed_task_handle;
65 }
66
PostDelayedTaskAt(subtle::PostDelayedTaskPassKey,const Location & from_here,OnceClosure task,TimeTicks delayed_run_time,subtle::DelayPolicy deadline_policy)67 bool SequencedTaskRunner::PostDelayedTaskAt(
68 subtle::PostDelayedTaskPassKey,
69 const Location& from_here,
70 OnceClosure task,
71 TimeTicks delayed_run_time,
72 subtle::DelayPolicy deadline_policy) {
73 return PostDelayedTask(from_here, std::move(task),
74 delayed_run_time.is_null()
75 ? base::TimeDelta()
76 : delayed_run_time - TimeTicks::Now());
77 }
78
RunOrPostTask(subtle::RunOrPostTaskPassKey,const Location & from_here,OnceClosure task)79 bool SequencedTaskRunner::RunOrPostTask(subtle::RunOrPostTaskPassKey,
80 const Location& from_here,
81 OnceClosure task) {
82 return PostTask(from_here, std::move(task));
83 }
84
85 // static
86 const scoped_refptr<SequencedTaskRunner>&
GetCurrentDefault()87 SequencedTaskRunner::GetCurrentDefault() {
88 CHECK(HasCurrentDefault())
89 << "Error: This caller requires a sequenced context (i.e. the current "
90 "task needs to run from a SequencedTaskRunner). If you're in a test "
91 "refer to //docs/threading_and_tasks_testing.md.";
92 return current_default_handle->task_runner_;
93 }
94
95 // static
HasCurrentDefault()96 bool SequencedTaskRunner::HasCurrentDefault() {
97 return !!current_default_handle && !!current_default_handle->task_runner_;
98 }
99
CurrentDefaultHandle(scoped_refptr<SequencedTaskRunner> task_runner)100 SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
101 scoped_refptr<SequencedTaskRunner> task_runner)
102 : CurrentDefaultHandle(std::move(task_runner), MayAlreadyExist{}) {
103 CHECK(!previous_handle_ || !previous_handle_->task_runner_);
104 }
105
~CurrentDefaultHandle()106 SequencedTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() {
107 DCHECK_EQ(current_default_handle, this);
108 current_default_handle = previous_handle_;
109 }
110
CurrentDefaultHandle(scoped_refptr<SequencedTaskRunner> task_runner,MayAlreadyExist)111 SequencedTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
112 scoped_refptr<SequencedTaskRunner> task_runner,
113 MayAlreadyExist)
114 : task_runner_(std::move(task_runner)),
115 previous_handle_(current_default_handle) {
116 // Support overriding the current default with a null task runner or a task
117 // runner that runs its tasks in the current sequence.
118 DCHECK(!task_runner_ || task_runner_->RunsTasksInCurrentSequence());
119 current_default_handle = this;
120 }
121
DeleteOrReleaseSoonInternal(const Location & from_here,void (* deleter)(const void *),const void * object)122 bool SequencedTaskRunner::DeleteOrReleaseSoonInternal(
123 const Location& from_here,
124 void (*deleter)(const void*),
125 const void* object) {
126 return PostNonNestableTask(from_here, BindOnce(deleter, object));
127 }
128
OnTaskRunnerDeleter(scoped_refptr<SequencedTaskRunner> task_runner)129 OnTaskRunnerDeleter::OnTaskRunnerDeleter(
130 scoped_refptr<SequencedTaskRunner> task_runner)
131 : task_runner_(std::move(task_runner)) {
132 }
133
134 OnTaskRunnerDeleter::~OnTaskRunnerDeleter() = default;
135
136 OnTaskRunnerDeleter::OnTaskRunnerDeleter(OnTaskRunnerDeleter&&) = default;
137
138 OnTaskRunnerDeleter& OnTaskRunnerDeleter::operator=(
139 OnTaskRunnerDeleter&&) = default;
140
141 } // namespace base
142