lazy_thread_pool_task_runner.cc 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127
  1. // Copyright 2017 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/task/lazy_thread_pool_task_runner.h"
  5. #include <atomic>
  6. #include <utility>
  7. #include "base/check_op.h"
  8. #include "base/lazy_instance_helpers.h"
  9. #include "base/task/thread_pool.h"
  10. #include "build/build_config.h"
  11. namespace base {
  12. namespace internal {
  13. namespace {
  14. ScopedLazyTaskRunnerListForTesting* g_scoped_lazy_task_runner_list_for_testing =
  15. nullptr;
  16. } // namespace
  17. template <typename TaskRunnerType, bool com_sta>
  18. void LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::Reset() {
  19. uintptr_t state = state_.load(std::memory_order_acquire);
  20. DCHECK_NE(state, kLazyInstanceStateCreating) << "Race: all threads should be "
  21. "unwound in unittests before "
  22. "resetting TaskRunners.";
  23. // Return if no reference is held by this instance.
  24. if (!state)
  25. return;
  26. // Release the reference acquired in Get().
  27. SequencedTaskRunner* task_runner = reinterpret_cast<TaskRunnerType*>(state);
  28. task_runner->Release();
  29. // Clear the state.
  30. state_.store(0, std::memory_order_relaxed);
  31. }
  32. template <>
  33. scoped_refptr<SequencedTaskRunner>
  34. LazyThreadPoolTaskRunner<SequencedTaskRunner, false>::Create() {
  35. // It is invalid to specify a SingleThreadTaskRunnerThreadMode with a
  36. // LazyThreadPoolSequencedTaskRunner.
  37. DCHECK_EQ(thread_mode_, SingleThreadTaskRunnerThreadMode::SHARED);
  38. return ThreadPool::CreateSequencedTaskRunner(traits_);
  39. }
  40. template <>
  41. scoped_refptr<SingleThreadTaskRunner>
  42. LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>::Create() {
  43. return ThreadPool::CreateSingleThreadTaskRunner(traits_, thread_mode_);
  44. }
  45. #if BUILDFLAG(IS_WIN)
  46. template <>
  47. scoped_refptr<SingleThreadTaskRunner>
  48. LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>::Create() {
  49. return ThreadPool::CreateCOMSTATaskRunner(traits_, thread_mode_);
  50. }
  51. #endif
  52. // static
  53. template <typename TaskRunnerType, bool com_sta>
  54. TaskRunnerType* LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::CreateRaw(
  55. void* void_self) {
  56. auto self =
  57. reinterpret_cast<LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>*>(
  58. void_self);
  59. scoped_refptr<TaskRunnerType> task_runner = self->Create();
  60. // Acquire a reference to the TaskRunner. The reference will either
  61. // never be released or be released in Reset(). The reference is not
  62. // managed by a scoped_refptr because adding a scoped_refptr member to
  63. // LazyThreadPoolTaskRunner would prevent its static initialization.
  64. task_runner->AddRef();
  65. // Reset this instance when the current
  66. // ScopedLazyTaskRunnerListForTesting is destroyed, if any.
  67. if (g_scoped_lazy_task_runner_list_for_testing) {
  68. g_scoped_lazy_task_runner_list_for_testing->AddCallback(
  69. BindOnce(&LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::Reset,
  70. Unretained(self)));
  71. }
  72. return task_runner.get();
  73. }
  74. template <typename TaskRunnerType, bool com_sta>
  75. scoped_refptr<TaskRunnerType>
  76. LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::Get() {
  77. return WrapRefCounted(subtle::GetOrCreateLazyPointer(
  78. state_, &LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::CreateRaw,
  79. reinterpret_cast<void*>(this), nullptr, nullptr));
  80. }
  81. template class LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
  82. template class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
  83. #if BUILDFLAG(IS_WIN)
  84. template class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
  85. #endif
  86. ScopedLazyTaskRunnerListForTesting::ScopedLazyTaskRunnerListForTesting() {
  87. DCHECK(!g_scoped_lazy_task_runner_list_for_testing);
  88. g_scoped_lazy_task_runner_list_for_testing = this;
  89. }
  90. ScopedLazyTaskRunnerListForTesting::~ScopedLazyTaskRunnerListForTesting() {
  91. internal::CheckedAutoLock auto_lock(lock_);
  92. for (auto& callback : callbacks_)
  93. std::move(callback).Run();
  94. g_scoped_lazy_task_runner_list_for_testing = nullptr;
  95. }
  96. void ScopedLazyTaskRunnerListForTesting::AddCallback(OnceClosure callback) {
  97. internal::CheckedAutoLock auto_lock(lock_);
  98. callbacks_.push_back(std::move(callback));
  99. }
  100. } // namespace internal
  101. } // namespace base