lazy_thread_pool_task_runner.h 9.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226
  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 <vector>
  7. #include "base/atomicops.h"
  8. #include "base/callback.h"
  9. #include "base/compiler_specific.h"
  10. #include "base/sequenced_task_runner.h"
  11. #include "base/single_thread_task_runner.h"
  12. #include "base/task/common/checked_lock.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 defined(OS_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. /* ThreadPool() as a trait is deprecated and implicit here */ \
  87. static_assert(!traits.use_thread_pool(), ""); \
  88. ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
  89. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
  90. __LINE__) = traits
  91. // |traits| are TaskTraits used when creating the SingleThreadTaskRunner.
  92. // |thread_mode| specifies whether the SingleThreadTaskRunner can share its
  93. // thread with other SingleThreadTaskRunners.
  94. #define LAZY_THREAD_POOL_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(traits, \
  95. thread_mode) \
  96. base::LazyThreadPoolSingleThreadTaskRunner::CreateInternal(traits, \
  97. thread_mode); \
  98. /* ThreadPool() as a trait is deprecated and implicit here */ \
  99. static_assert(!traits.use_thread_pool(), ""); \
  100. ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
  101. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
  102. __LINE__) = traits; \
  103. ALLOW_UNUSED_TYPE constexpr base::SingleThreadTaskRunnerThreadMode \
  104. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
  105. __LINE__) = thread_mode
  106. // |traits| are TaskTraits used when creating the COM STA
  107. // SingleThreadTaskRunner. |thread_mode| specifies whether the COM STA
  108. // SingleThreadTaskRunner can share its thread with other
  109. // SingleThreadTaskRunners.
  110. #define LAZY_COM_STA_TASK_RUNNER_INITIALIZER(traits, thread_mode) \
  111. base::LazyThreadPoolCOMSTATaskRunner::CreateInternal(traits, thread_mode); \
  112. /* ThreadPool() as a trait is deprecated and implicit here */ \
  113. static_assert(!traits.use_thread_pool(), ""); \
  114. ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
  115. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
  116. __LINE__) = traits; \
  117. ALLOW_UNUSED_TYPE constexpr base::SingleThreadTaskRunnerThreadMode \
  118. LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
  119. __LINE__) = thread_mode
  120. namespace internal {
  121. template <typename TaskRunnerType, bool com_sta>
  122. class BASE_EXPORT LazyThreadPoolTaskRunner {
  123. public:
  124. // Use the macros above rather than a direct call to this.
  125. //
  126. // |traits| are TaskTraits to use to create the TaskRunner. If this
  127. // LazyThreadPoolTaskRunner is specialized to create a SingleThreadTaskRunner,
  128. // |thread_mode| specifies whether the SingleThreadTaskRunner can share its
  129. // thread with other SingleThreadTaskRunner. Otherwise, it is unused.
  130. static constexpr LazyThreadPoolTaskRunner CreateInternal(
  131. const TaskTraits& traits,
  132. SingleThreadTaskRunnerThreadMode thread_mode =
  133. SingleThreadTaskRunnerThreadMode::SHARED) {
  134. return LazyThreadPoolTaskRunner(traits, thread_mode);
  135. }
  136. // Returns the TaskRunner held by this instance. Creates it if it didn't
  137. // already exist. Thread-safe.
  138. scoped_refptr<TaskRunnerType> Get();
  139. private:
  140. constexpr LazyThreadPoolTaskRunner(
  141. const TaskTraits& traits,
  142. SingleThreadTaskRunnerThreadMode thread_mode =
  143. SingleThreadTaskRunnerThreadMode::SHARED)
  144. : traits_(traits), thread_mode_(thread_mode) {}
  145. // Releases the TaskRunner held by this instance.
  146. void Reset();
  147. // Creates and returns a new TaskRunner.
  148. scoped_refptr<TaskRunnerType> Create();
  149. // Creates a new TaskRunner via Create(), adds an explicit ref to it, and
  150. // returns it raw. Used as an adapter for lazy instance helpers. Static and
  151. // takes |this| as an explicit param to match the void* signature of
  152. // GetOrCreateLazyPointer().
  153. static TaskRunnerType* CreateRaw(void* void_self);
  154. // TaskTraits to create the TaskRunner.
  155. const TaskTraits traits_;
  156. // SingleThreadTaskRunnerThreadMode to create the TaskRunner.
  157. const SingleThreadTaskRunnerThreadMode thread_mode_;
  158. // Can have 3 states:
  159. // - This instance does not hold a TaskRunner: 0
  160. // - This instance is creating a TaskRunner: kLazyInstanceStateCreating
  161. // - This instance holds a TaskRunner: Pointer to the TaskRunner.
  162. // LazyInstance's internals are reused to handle transition between states.
  163. subtle::AtomicWord state_ = 0;
  164. // No DISALLOW_COPY_AND_ASSIGN since that prevents static initialization with
  165. // Visual Studio (warning C4592: 'symbol will be dynamically initialized
  166. // (implementation limitation))'.
  167. };
  168. // When a LazyThreadPoolTaskRunner becomes active (invokes Get()), it adds a
  169. // callback to the current ScopedLazyTaskRunnerListForTesting, if any.
  170. // Callbacks run when the ScopedLazyTaskRunnerListForTesting is
  171. // destroyed. In a test process, a ScopedLazyTaskRunnerListForTesting
  172. // must be instantiated before any LazyThreadPoolTaskRunner becomes active.
  173. class BASE_EXPORT ScopedLazyTaskRunnerListForTesting {
  174. public:
  175. ScopedLazyTaskRunnerListForTesting();
  176. ~ScopedLazyTaskRunnerListForTesting();
  177. private:
  178. friend class LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
  179. friend class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
  180. #if defined(OS_WIN)
  181. friend class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
  182. #endif
  183. // Add |callback| to the list of callbacks to run on destruction.
  184. void AddCallback(OnceClosure callback);
  185. CheckedLock lock_;
  186. // List of callbacks to run on destruction.
  187. std::vector<OnceClosure> callbacks_ GUARDED_BY(lock_);
  188. DISALLOW_COPY_AND_ASSIGN(ScopedLazyTaskRunnerListForTesting);
  189. };
  190. } // namespace internal
  191. } // namespace base
  192. #endif // BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_