• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
18 namespace base {
19 
20 namespace {
21 
22 constinit thread_local SingleThreadTaskRunner::CurrentDefaultHandle*
23     current_default_handle = nullptr;
24 
25 // This function can be removed, and the calls below replaced with direct
26 // variable accesses, once the MSAN workaround is not necessary.
GetCurrentDefaultHandle()27 SingleThreadTaskRunner::CurrentDefaultHandle* GetCurrentDefaultHandle() {
28   // Workaround false-positive MSAN use-of-uninitialized-value on
29   // thread_local storage for loaded libraries:
30   // https://github.com/google/sanitizers/issues/1265
31   MSAN_UNPOISON(&current_default_handle,
32                 sizeof(SingleThreadTaskRunner::CurrentDefaultHandle*));
33 
34   return current_default_handle;
35 }
36 
37 }  // namespace
38 
BelongsToCurrentThread() const39 bool SingleThreadTaskRunner::BelongsToCurrentThread() const {
40   return RunsTasksInCurrentSequence();
41 }
42 
43 // static
44 const scoped_refptr<SingleThreadTaskRunner>&
GetCurrentDefault()45 SingleThreadTaskRunner::GetCurrentDefault() {
46   const auto* const handle = GetCurrentDefaultHandle();
47   CHECK(handle && handle->task_runner_)
48       << "Error: This caller requires a single-threaded context (i.e. the "
49          "current task needs to run from a SingleThreadTaskRunner). If you're "
50          "in a test refer to //docs/threading_and_tasks_testing.md."
51       << (SequencedTaskRunner::HasCurrentDefault()
52               ? " Note: base::SequencedTaskRunner::GetCurrentDefault() "
53                 "is set; "
54                 "consider using it if the current task can run from a "
55                 "SequencedTaskRunner."
56               : "");
57   return handle->task_runner_;
58 }
59 
60 // static
HasCurrentDefault()61 bool SingleThreadTaskRunner::HasCurrentDefault() {
62   return !!GetCurrentDefaultHandle() &&
63          !!GetCurrentDefaultHandle()->task_runner_;
64 }
65 
CurrentDefaultHandle(scoped_refptr<SingleThreadTaskRunner> task_runner)66 SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
67     scoped_refptr<SingleThreadTaskRunner> task_runner)
68     : CurrentDefaultHandle(std::move(task_runner), MayAlreadyExist{}) {
69   CHECK(!previous_handle_ || !previous_handle_->task_runner_);
70 }
71 
~CurrentDefaultHandle()72 SingleThreadTaskRunner::CurrentDefaultHandle::~CurrentDefaultHandle() {
73   DCHECK_EQ(GetCurrentDefaultHandle(), this);
74   current_default_handle = previous_handle_;
75 }
76 
CurrentDefaultHandle(scoped_refptr<SingleThreadTaskRunner> task_runner,MayAlreadyExist)77 SingleThreadTaskRunner::CurrentDefaultHandle::CurrentDefaultHandle(
78     scoped_refptr<SingleThreadTaskRunner> task_runner,
79     MayAlreadyExist)
80     : task_runner_(std::move(task_runner)),
81       previous_handle_(GetCurrentDefaultHandle()),
82       sequenced_handle_(
83           task_runner_,
84           SequencedTaskRunner::CurrentDefaultHandle::MayAlreadyExist{}) {
85   // Support overriding the current default with a null task runner or a task
86   // runner that belongs to the current thread.
87   DCHECK(!task_runner_ || task_runner_->BelongsToCurrentThread());
88   current_default_handle = this;
89 }
90 
91 SingleThreadTaskRunner::CurrentHandleOverrideForTesting::
CurrentHandleOverrideForTesting(scoped_refptr<SingleThreadTaskRunner> overriding_task_runner)92     CurrentHandleOverrideForTesting(
93         scoped_refptr<SingleThreadTaskRunner> overriding_task_runner)
94     : current_default_handle_(std::move(overriding_task_runner),
95                               CurrentDefaultHandle::MayAlreadyExist{}),
96       no_running_during_override_(
97           std::make_unique<ScopedDisallowRunningRunLoop>()) {}
98 
99 SingleThreadTaskRunner::CurrentHandleOverrideForTesting::
100     ~CurrentHandleOverrideForTesting() = default;
101 
102 }  // namespace base
103