thread_task_runner_handle.cc 3.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108
  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. #include "base/threading/thread_task_runner_handle.h"
  5. #include <memory>
  6. #include <utility>
  7. #include "base/bind.h"
  8. #include "base/check_op.h"
  9. #include "base/dcheck_is_on.h"
  10. #include "base/lazy_instance.h"
  11. #include "base/run_loop.h"
  12. #include "base/threading/sequenced_task_runner_handle.h"
  13. #include "base/threading/thread_local.h"
  14. namespace base {
  15. namespace {
  16. base::LazyInstance<base::ThreadLocalPointer<ThreadTaskRunnerHandle>>::Leaky
  17. thread_task_runner_tls = LAZY_INSTANCE_INITIALIZER;
  18. } // namespace
  19. // static
  20. const scoped_refptr<SingleThreadTaskRunner>& ThreadTaskRunnerHandle::Get() {
  21. const ThreadTaskRunnerHandle* current =
  22. thread_task_runner_tls.Pointer()->Get();
  23. CHECK(current)
  24. << "Error: This caller requires a single-threaded context (i.e. the "
  25. "current task needs to run from a SingleThreadTaskRunner). If you're "
  26. "in a test refer to //docs/threading_and_tasks_testing.md."
  27. << (SequencedTaskRunnerHandle::IsSet()
  28. ? " Note: base::SequencedTaskRunnerHandle::Get() is set; "
  29. "consider using it if the current task can run from a "
  30. "SequencedTaskRunner."
  31. : "");
  32. return current->task_runner_;
  33. }
  34. // static
  35. bool ThreadTaskRunnerHandle::IsSet() {
  36. return !!thread_task_runner_tls.Pointer()->Get();
  37. }
  38. ThreadTaskRunnerHandle::ThreadTaskRunnerHandle(
  39. scoped_refptr<SingleThreadTaskRunner> task_runner)
  40. : task_runner_(std::move(task_runner)),
  41. sequenced_task_runner_handle_(task_runner_) {
  42. DCHECK(task_runner_->BelongsToCurrentThread());
  43. DCHECK(!thread_task_runner_tls.Pointer()->Get());
  44. thread_task_runner_tls.Pointer()->Set(this);
  45. }
  46. ThreadTaskRunnerHandle::~ThreadTaskRunnerHandle() {
  47. DCHECK(task_runner_->BelongsToCurrentThread());
  48. DCHECK_EQ(thread_task_runner_tls.Pointer()->Get(), this);
  49. thread_task_runner_tls.Pointer()->Set(nullptr);
  50. }
  51. ThreadTaskRunnerHandleOverride::ThreadTaskRunnerHandleOverride(
  52. scoped_refptr<SingleThreadTaskRunner> overriding_task_runner,
  53. bool allow_nested_runloop) {
  54. DCHECK(!SequencedTaskRunnerHandle::IsSet() || ThreadTaskRunnerHandle::IsSet())
  55. << "ThreadTaskRunnerHandleOverride is not compatible with a "
  56. "SequencedTaskRunnerHandle already being set on this thread (except "
  57. "when it's set by the current ThreadTaskRunnerHandle).";
  58. if (!ThreadTaskRunnerHandle::IsSet()) {
  59. top_level_thread_task_runner_handle_.emplace(
  60. std::move(overriding_task_runner));
  61. return;
  62. }
  63. #if DCHECK_IS_ON()
  64. expected_task_runner_before_restore_ = overriding_task_runner.get();
  65. #endif
  66. ThreadTaskRunnerHandle* ttrh = thread_task_runner_tls.Pointer()->Get();
  67. ttrh->sequenced_task_runner_handle_.task_runner_ = overriding_task_runner;
  68. ttrh->task_runner_.swap(overriding_task_runner);
  69. // Due to the swap, now `ttrh->task_runner_` points to the overriding task
  70. // runner and `overriding_task_runner_` points to the previous task runner.
  71. task_runner_to_restore_ = std::move(overriding_task_runner);
  72. if (!allow_nested_runloop) {
  73. no_running_during_override_ =
  74. std::make_unique<ScopedDisallowRunningRunLoop>();
  75. }
  76. }
  77. ThreadTaskRunnerHandleOverride::~ThreadTaskRunnerHandleOverride() {
  78. if (task_runner_to_restore_) {
  79. ThreadTaskRunnerHandle* ttrh = thread_task_runner_tls.Pointer()->Get();
  80. #if DCHECK_IS_ON()
  81. DCHECK_EQ(expected_task_runner_before_restore_, ttrh->task_runner_.get())
  82. << "Nested overrides must expire their ThreadTaskRunnerHandleOverride "
  83. "in LIFO order.";
  84. #endif
  85. ttrh->sequenced_task_runner_handle_.task_runner_ = task_runner_to_restore_;
  86. ttrh->task_runner_.swap(task_runner_to_restore_);
  87. }
  88. }
  89. } // namespace base