1 // Copyright 2016 The Chromium Authors. All rights reserved.
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/single_thread_task_runner.h"
6
7 #include <memory>
8 #include <utility>
9
10 #include "base/check.h"
11 #include "base/check_op.h"
12 #include "base/compiler_specific.h"
13 #include "base/dcheck_is_on.h"
14 #include "base/functional/bind.h"
15 #include "base/lazy_instance.h"
16 #include "base/run_loop.h"
17 #include "third_party/abseil-cpp/absl/base/attributes.h"
18
19 namespace base {
20
21 namespace {
22
23 ABSL_CONST_INIT thread_local SingleThreadTaskRunner::CurrentDefaultHandle*
24 current_default_handle = nullptr;
25
26 // This function can be removed, and the calls below replaced with direct
27 // variable accesses, once the MSAN workaround is not necessary.
GetCurrentDefaultHandle()28 SingleThreadTaskRunner::CurrentDefaultHandle* GetCurrentDefaultHandle() {
29 // Workaround false-positive MSAN use-of-uninitialized-value on
30 // thread_local storage for loaded libraries:
31 // https://github.com/google/sanitizers/issues/1265
32 MSAN_UNPOISON(¤t_default_handle,
33 sizeof(SingleThreadTaskRunner::CurrentDefaultHandle*));
34
35 return current_default_handle;
36 }
37
38 } // namespace
39
40 // static
41 const scoped_refptr<SingleThreadTaskRunner>&
GetCurrentDefault()42 SingleThreadTaskRunner::GetCurrentDefault() {
43 const auto* const handle = GetCurrentDefaultHandle();
44 CHECK(handle)
45 << "Error: This caller requires a single-threaded context (i.e. the "
46 "current task needs to run from a SingleThreadTaskRunner). If you're "
47 "in a test refer to //docs/threading_and_tasks_testing.md."
48 << (SequencedTaskRunner::HasCurrentDefault()
49 ? " Note: base::SequencedTaskRunner::GetCurrentDefault() "
50 "is set; "
51 "consider using it if the current task can run from a "
52 "SequencedTaskRunner."
53 : "");
54 return handle->task_runner_;
55 }
56
57 // static
HasCurrentDefault()58 bool SingleThreadTaskRunner::HasCurrentDefault() {
59 return !!GetCurrentDefaultHandle();
60 }
61
CurrentDefaultHandle(scoped_refptr<SingleThreadTaskRunner> task_runner)62 SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
63 scoped_refptr<SingleThreadTaskRunner> task_runner)
64 : resetter_(¤t_default_handle, this, nullptr),
65 task_runner_(std::move(task_runner)),
66 sequenced_task_runner_current_default_(task_runner_) {
67 DCHECK(task_runner_->BelongsToCurrentThread());
68 }
69
~CurrentDefaultHandle()70 SingleThreadTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() {
71 DCHECK(task_runner_->BelongsToCurrentThread());
72 DCHECK_EQ(GetCurrentDefaultHandle(), this);
73 }
74
CurrentHandleOverride(scoped_refptr<SingleThreadTaskRunner> overriding_task_runner,bool allow_nested_runloop)75 SingleThreadTaskRunner::CurrentHandleOverride::CurrentHandleOverride(
76 scoped_refptr<SingleThreadTaskRunner> overriding_task_runner,
77 bool allow_nested_runloop) {
78 DCHECK(!SequencedTaskRunner::HasCurrentDefault() ||
79 SingleThreadTaskRunner::HasCurrentDefault())
80 << "SingleThreadTaskRunner::CurrentHandleOverride is not compatible with "
81 "a SequencedTaskRunner::CurrentDefaultHandle already "
82 "being set on this thread (except when it's "
83 "set by the current "
84 "SingleThreadTaskRunner::CurrentDefaultHandle).";
85
86 if (!SingleThreadTaskRunner::HasCurrentDefault()) {
87 top_level_thread_task_runner_current_default_.emplace(
88 std::move(overriding_task_runner));
89 return;
90 }
91
92 #if DCHECK_IS_ON()
93 expected_task_runner_before_restore_ = overriding_task_runner.get();
94 #endif
95 auto* const handle = GetCurrentDefaultHandle();
96 SequencedTaskRunner::SetCurrentDefaultHandleTaskRunner(
97 handle->sequenced_task_runner_current_default_, overriding_task_runner);
98 handle->task_runner_.swap(overriding_task_runner);
99 // Due to the swap, now `handle->task_runner_` points to the overriding task
100 // runner and `overriding_task_runner_` points to the previous task runner.
101 task_runner_to_restore_ = std::move(overriding_task_runner);
102
103 if (!allow_nested_runloop) {
104 no_running_during_override_ =
105 std::make_unique<ScopedDisallowRunningRunLoop>();
106 }
107 }
108
~CurrentHandleOverride()109 SingleThreadTaskRunner::CurrentHandleOverride::~CurrentHandleOverride() {
110 if (task_runner_to_restore_) {
111 auto* const handle = GetCurrentDefaultHandle();
112 #if DCHECK_IS_ON()
113 DCHECK_EQ(expected_task_runner_before_restore_, handle->task_runner_.get())
114 << "Nested overrides must expire their "
115 "SingleThreadTaskRunner::CurrentHandleOverride "
116 "in LIFO order.";
117 #endif
118
119 SequencedTaskRunner::SetCurrentDefaultHandleTaskRunner(
120 handle->sequenced_task_runner_current_default_,
121 task_runner_to_restore_);
122 handle->task_runner_.swap(task_runner_to_restore_);
123 }
124 }
125
126 } // namespace base
127