1 // Copyright 2016 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/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
BelongsToCurrentThread() const40 bool SingleThreadTaskRunner::BelongsToCurrentThread() const {
41 return RunsTasksInCurrentSequence();
42 }
43
44 // static
45 const scoped_refptr<SingleThreadTaskRunner>&
GetCurrentDefault()46 SingleThreadTaskRunner::GetCurrentDefault() {
47 const auto* const handle = GetCurrentDefaultHandle();
48 CHECK(handle && handle->task_runner_)
49 << "Error: This caller requires a single-threaded context (i.e. the "
50 "current task needs to run from a SingleThreadTaskRunner). If you're "
51 "in a test refer to //docs/threading_and_tasks_testing.md."
52 << (SequencedTaskRunner::HasCurrentDefault()
53 ? " Note: base::SequencedTaskRunner::GetCurrentDefault() "
54 "is set; "
55 "consider using it if the current task can run from a "
56 "SequencedTaskRunner."
57 : "");
58 return handle->task_runner_;
59 }
60
61 // static
HasCurrentDefault()62 bool SingleThreadTaskRunner::HasCurrentDefault() {
63 return !!GetCurrentDefaultHandle() &&
64 !!GetCurrentDefaultHandle()->task_runner_;
65 }
66
CurrentDefaultHandle(scoped_refptr<SingleThreadTaskRunner> task_runner)67 SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
68 scoped_refptr<SingleThreadTaskRunner> task_runner)
69 : CurrentDefaultHandle(std::move(task_runner), MayAlreadyExist{}) {
70 CHECK(!previous_handle_ || !previous_handle_->task_runner_);
71 }
72
~CurrentDefaultHandle()73 SingleThreadTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() {
74 DCHECK_EQ(GetCurrentDefaultHandle(), this);
75 current_default_handle = previous_handle_;
76 }
77
CurrentDefaultHandle(scoped_refptr<SingleThreadTaskRunner> task_runner,MayAlreadyExist)78 SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
79 scoped_refptr<SingleThreadTaskRunner> task_runner,
80 MayAlreadyExist)
81 : task_runner_(std::move(task_runner)),
82 previous_handle_(GetCurrentDefaultHandle()),
83 sequenced_handle_(
84 task_runner_,
85 SequencedTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}) {
86 // Support overriding the current default with a null task runner or a task
87 // runner that belongs to the current thread.
88 DCHECK(!task_runner_ || task_runner_->BelongsToCurrentThread());
89 current_default_handle = this;
90 }
91
92 SingleThreadTaskRunner::CurrentHandleOverrideForTesting::
CurrentHandleOverrideForTesting(scoped_refptr<SingleThreadTaskRunner> overriding_task_runner)93 CurrentHandleOverrideForTesting(
94 scoped_refptr<SingleThreadTaskRunner> overriding_task_runner)
95 : current_default_handle_(std::move(overriding_task_runner),
96 CurrentDefaultHandle::MayAlreadyExist{}),
97 no_running_during_override_(
98 std::make_unique<ScopedDisallowRunningRunLoop>()) {}
99
100 SingleThreadTaskRunner::CurrentHandleOverrideForTesting::
101 ~CurrentHandleOverrideForTesting() = default;
102
103 } // namespace base
104