lazy_thread_pool_task_runner.h 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224
  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. #ifndef BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_
  5. #define BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_
  6. #include <atomic>
  7. #include <vector>
  8. #include "base/base_export.h"
  9. #include "base/callback.h"
  10. #include "base/task/common/checked_lock.h"
  11. #include "base/task/sequenced_task_runner.h"
  12. #include "base/task/single_thread_task_runner.h"
  13. #include "base/task/single_thread_task_runner_thread_mode.h"
  14. #include "base/task/task_traits.h"
  15. #include "base/thread_annotations.h"
  16. #include "build/build_config.h"
  17. // Lazy(Sequenced|SingleThread|COMSTA)TaskRunner lazily creates a TaskRunner.
  18. //
  19. // Lazy(Sequenced|SingleThread|COMSTA)TaskRunner is meant to be instantiated in
  20. // an anonymous namespace (no static initializer is generated) and used to post
  21. // tasks to the same thread-pool-bound sequence/thread from pieces of code that
  22. // don't have a better way of sharing a TaskRunner. It is important to use this
  23. // class instead of a self-managed global variable or LazyInstance so that the
  24. // TaskRunners do not outlive the scope of the TaskEnvironment in unit tests
  25. // (otherwise the next test in the same process will die in use-after-frees).
  26. //
  27. // IMPORTANT: Only use this API as a last resort. Prefer storing a
  28. // (Sequenced|SingleThread)TaskRunner returned by
  29. // base::ThreadPool::Create(Sequenced|SingleThread|COMSTA)TaskRunner() as a
  30. // member on an object accessible by all PostTask() call sites.
  31. //
  32. // Example usage 1:
  33. //
  34. // namespace {
  35. // base::LazyThreadPoolSequencedTaskRunner g_sequenced_task_runner =
  36. // LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
  37. // base::TaskTraits(base::MayBlock(),
  38. // base::TaskPriority::USER_VISIBLE));
  39. // } // namespace
  40. //
  41. // void SequencedFunction() {
  42. // // Different invocations of this function post to the same
  43. // // MayBlock() SequencedTaskRunner.
  44. // g_sequenced_task_runner.Get()->PostTask(FROM_HERE, base::BindOnce(...));
  45. // }
  46. //
  47. // Example usage 2:
  48. //
  49. // namespace {
  50. // base::LazyThreadPoolSequencedTaskRunner g_sequenced_task_task_runner =
  51. // LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
  52. // base::TaskTraits(base::MayBlock()));
  53. // } // namespace
  54. //
  55. // // Code from different files can access the SequencedTaskRunner via this
  56. // // function.
  57. // scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
  58. // return g_sequenced_task_runner.Get();
  59. // }
  60. namespace base {
  61. namespace internal {
  62. template <typename TaskRunnerType, bool com_sta>
  63. class BASE_EXPORT LazyThreadPoolTaskRunner;
  64. } // namespace internal
  65. // Lazy SequencedTaskRunner.
  66. using LazyThreadPoolSequencedTaskRunner =
  67. internal::LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
  68. // Lazy SingleThreadTaskRunner.
  69. using LazyThreadPoolSingleThreadTaskRunner =
  70. internal::LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
  71. #if BUILDFLAG(IS_WIN)
  72. // Lazy COM-STA enabled SingleThreadTaskRunner.
  73. using LazyThreadPoolCOMSTATaskRunner =
  74. internal::LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
  75. #endif
  76. // Helper macros to generate a variable name by concatenation.
  77. #define LAZY_TASK_RUNNER_CONCATENATE_INTERNAL2(a, b) a##b
  78. #define LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(a, b) \
  79. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL2(a, b)
  80. // Use the macros below to initialize a LazyThreadPoolTaskRunner. These macros
  81. // verify that their arguments are constexpr, which is important to prevent the
  82. // generation of a static initializer.
  83. // |traits| are TaskTraits used when creating the SequencedTaskRunner.
  84. #define LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(traits) \
  85. base::LazyThreadPoolSequencedTaskRunner::CreateInternal(traits); \
  86. [[maybe_unused]] constexpr base::TaskTraits \
  87. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
  88. __LINE__) = traits
  89. // |traits| are TaskTraits used when creating the SingleThreadTaskRunner.
  90. // |thread_mode| specifies whether the SingleThreadTaskRunner can share its
  91. // thread with other SingleThreadTaskRunners.
  92. #define LAZY_THREAD_POOL_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(traits, \
  93. thread_mode) \
  94. base::LazyThreadPoolSingleThreadTaskRunner::CreateInternal(traits, \
  95. thread_mode); \
  96. [[maybe_unused]] constexpr base::TaskTraits \
  97. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
  98. __LINE__) = traits; \
  99. [[maybe_unused]] constexpr base::SingleThreadTaskRunnerThreadMode \
  100. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
  101. __LINE__) = thread_mode
  102. // |traits| are TaskTraits used when creating the COM STA
  103. // SingleThreadTaskRunner. |thread_mode| specifies whether the COM STA
  104. // SingleThreadTaskRunner can share its thread with other
  105. // SingleThreadTaskRunners.
  106. #define LAZY_COM_STA_TASK_RUNNER_INITIALIZER(traits, thread_mode) \
  107. base::LazyThreadPoolCOMSTATaskRunner::CreateInternal(traits, thread_mode); \
  108. [[maybe_unused]] constexpr base::TaskTraits \
  109. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
  110. __LINE__) = traits; \
  111. [[maybe_unused]] constexpr base::SingleThreadTaskRunnerThreadMode \
  112. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
  113. __LINE__) = thread_mode
  114. namespace internal {
  115. template <typename TaskRunnerType, bool com_sta>
  116. class BASE_EXPORT LazyThreadPoolTaskRunner {
  117. public:
  118. // Use the macros above rather than a direct call to this.
  119. //
  120. // |traits| are TaskTraits to use to create the TaskRunner. If this
  121. // LazyThreadPoolTaskRunner is specialized to create a SingleThreadTaskRunner,
  122. // |thread_mode| specifies whether the SingleThreadTaskRunner can share its
  123. // thread with other SingleThreadTaskRunner. Otherwise, it is unused.
  124. static constexpr LazyThreadPoolTaskRunner CreateInternal(
  125. const TaskTraits& traits,
  126. SingleThreadTaskRunnerThreadMode thread_mode =
  127. SingleThreadTaskRunnerThreadMode::SHARED) {
  128. return LazyThreadPoolTaskRunner(traits, thread_mode);
  129. }
  130. // Returns the TaskRunner held by this instance. Creates it if it didn't
  131. // already exist. Thread-safe.
  132. scoped_refptr<TaskRunnerType> Get();
  133. private:
  134. constexpr LazyThreadPoolTaskRunner(
  135. const TaskTraits& traits,
  136. SingleThreadTaskRunnerThreadMode thread_mode =
  137. SingleThreadTaskRunnerThreadMode::SHARED)
  138. : traits_(traits), thread_mode_(thread_mode) {}
  139. // Releases the TaskRunner held by this instance.
  140. void Reset();
  141. // Creates and returns a new TaskRunner.
  142. scoped_refptr<TaskRunnerType> Create();
  143. // Creates a new TaskRunner via Create(), adds an explicit ref to it, and
  144. // returns it raw. Used as an adapter for lazy instance helpers. Static and
  145. // takes |this| as an explicit param to match the void* signature of
  146. // GetOrCreateLazyPointer().
  147. static TaskRunnerType* CreateRaw(void* void_self);
  148. // TaskTraits to create the TaskRunner.
  149. const TaskTraits traits_;
  150. // SingleThreadTaskRunnerThreadMode to create the TaskRunner.
  151. const SingleThreadTaskRunnerThreadMode thread_mode_;
  152. // Can have 3 states:
  153. // - This instance does not hold a TaskRunner: 0
  154. // - This instance is creating a TaskRunner: kLazyInstanceStateCreating
  155. // - This instance holds a TaskRunner: Pointer to the TaskRunner.
  156. // LazyInstance's internals are reused to handle transition between states.
  157. std::atomic<uintptr_t> state_ = 0;
  158. // No DISALLOW_COPY_AND_ASSIGN since that prevents static initialization with
  159. // Visual Studio (warning C4592: 'symbol will be dynamically initialized
  160. // (implementation limitation))'.
  161. };
  162. // When a LazyThreadPoolTaskRunner becomes active (invokes Get()), it adds a
  163. // callback to the current ScopedLazyTaskRunnerListForTesting, if any.
  164. // Callbacks run when the ScopedLazyTaskRunnerListForTesting is
  165. // destroyed. In a test process, a ScopedLazyTaskRunnerListForTesting
  166. // must be instantiated before any LazyThreadPoolTaskRunner becomes active.
  167. class BASE_EXPORT ScopedLazyTaskRunnerListForTesting {
  168. public:
  169. ScopedLazyTaskRunnerListForTesting();
  170. ScopedLazyTaskRunnerListForTesting(
  171. const ScopedLazyTaskRunnerListForTesting&) = delete;
  172. ScopedLazyTaskRunnerListForTesting& operator=(
  173. const ScopedLazyTaskRunnerListForTesting&) = delete;
  174. ~ScopedLazyTaskRunnerListForTesting();
  175. private:
  176. friend class LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
  177. friend class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
  178. #if BUILDFLAG(IS_WIN)
  179. friend class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
  180. #endif
  181. // Add |callback| to the list of callbacks to run on destruction.
  182. void AddCallback(OnceClosure callback);
  183. CheckedLock lock_;
  184. // List of callbacks to run on destruction.
  185. std::vector<OnceClosure> callbacks_ GUARDED_BY(lock_);
  186. };
  187. } // namespace internal
  188. } // namespace base
  189. #endif // BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_