123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226 |
- // Copyright 2017 The Chromium Authors. All rights reserved.
- // Use of this source code is governed by a BSD-style license that can be
- // found in the LICENSE file.
- #ifndef BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_
- #define BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_
- #include <vector>
- #include "base/atomicops.h"
- #include "base/callback.h"
- #include "base/compiler_specific.h"
- #include "base/sequenced_task_runner.h"
- #include "base/single_thread_task_runner.h"
- #include "base/task/common/checked_lock.h"
- #include "base/task/single_thread_task_runner_thread_mode.h"
- #include "base/task/task_traits.h"
- #include "base/thread_annotations.h"
- #include "build/build_config.h"
- // Lazy(Sequenced|SingleThread|COMSTA)TaskRunner lazily creates a TaskRunner.
- //
- // Lazy(Sequenced|SingleThread|COMSTA)TaskRunner is meant to be instantiated in
- // an anonymous namespace (no static initializer is generated) and used to post
- // tasks to the same thread-pool-bound sequence/thread from pieces of code that
- // don't have a better way of sharing a TaskRunner. It is important to use this
- // class instead of a self-managed global variable or LazyInstance so that the
- // TaskRunners do not outlive the scope of the TaskEnvironment in unit tests
- // (otherwise the next test in the same process will die in use-after-frees).
- //
- // IMPORTANT: Only use this API as a last resort. Prefer storing a
- // (Sequenced|SingleThread)TaskRunner returned by
- // base::ThreadPool::Create(Sequenced|SingleThread|COMSTA)TaskRunner() as a
- // member on an object accessible by all PostTask() call sites.
- //
- // Example usage 1:
- //
- // namespace {
- // base::LazyThreadPoolSequencedTaskRunner g_sequenced_task_runner =
- // LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
- // base::TaskTraits(base::MayBlock(),
- // base::TaskPriority::USER_VISIBLE));
- // } // namespace
- //
- // void SequencedFunction() {
- // // Different invocations of this function post to the same
- // // MayBlock() SequencedTaskRunner.
- // g_sequenced_task_runner.Get()->PostTask(FROM_HERE, base::BindOnce(...));
- // }
- //
- // Example usage 2:
- //
- // namespace {
- // base::LazyThreadPoolSequencedTaskRunner g_sequenced_task_task_runner =
- // LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(
- // base::TaskTraits(base::MayBlock()));
- // } // namespace
- //
- // // Code from different files can access the SequencedTaskRunner via this
- // // function.
- // scoped_refptr<base::SequencedTaskRunner> GetTaskRunner() {
- // return g_sequenced_task_runner.Get();
- // }
- namespace base {
- namespace internal {
- template <typename TaskRunnerType, bool com_sta>
- class BASE_EXPORT LazyThreadPoolTaskRunner;
- } // namespace internal
- // Lazy SequencedTaskRunner.
- using LazyThreadPoolSequencedTaskRunner =
- internal::LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
- // Lazy SingleThreadTaskRunner.
- using LazyThreadPoolSingleThreadTaskRunner =
- internal::LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
- #if defined(OS_WIN)
- // Lazy COM-STA enabled SingleThreadTaskRunner.
- using LazyThreadPoolCOMSTATaskRunner =
- internal::LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
- #endif
- // Helper macros to generate a variable name by concatenation.
- #define LAZY_TASK_RUNNER_CONCATENATE_INTERNAL2(a, b) a##b
- #define LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(a, b) \
- LAZY_TASK_RUNNER_CONCATENATE_INTERNAL2(a, b)
- // Use the macros below to initialize a LazyThreadPoolTaskRunner. These macros
- // verify that their arguments are constexpr, which is important to prevent the
- // generation of a static initializer.
- // |traits| are TaskTraits used when creating the SequencedTaskRunner.
- #define LAZY_THREAD_POOL_SEQUENCED_TASK_RUNNER_INITIALIZER(traits) \
- base::LazyThreadPoolSequencedTaskRunner::CreateInternal(traits); \
- /* ThreadPool() as a trait is deprecated and implicit here */ \
- static_assert(!traits.use_thread_pool(), ""); \
- ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
- LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
- __LINE__) = traits
- // |traits| are TaskTraits used when creating the SingleThreadTaskRunner.
- // |thread_mode| specifies whether the SingleThreadTaskRunner can share its
- // thread with other SingleThreadTaskRunners.
- #define LAZY_THREAD_POOL_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(traits, \
- thread_mode) \
- base::LazyThreadPoolSingleThreadTaskRunner::CreateInternal(traits, \
- thread_mode); \
- /* ThreadPool() as a trait is deprecated and implicit here */ \
- static_assert(!traits.use_thread_pool(), ""); \
- ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
- LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
- __LINE__) = traits; \
- ALLOW_UNUSED_TYPE constexpr base::SingleThreadTaskRunnerThreadMode \
- LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
- __LINE__) = thread_mode
- // |traits| are TaskTraits used when creating the COM STA
- // SingleThreadTaskRunner. |thread_mode| specifies whether the COM STA
- // SingleThreadTaskRunner can share its thread with other
- // SingleThreadTaskRunners.
- #define LAZY_COM_STA_TASK_RUNNER_INITIALIZER(traits, thread_mode) \
- base::LazyThreadPoolCOMSTATaskRunner::CreateInternal(traits, thread_mode); \
- /* ThreadPool() as a trait is deprecated and implicit here */ \
- static_assert(!traits.use_thread_pool(), ""); \
- ALLOW_UNUSED_TYPE constexpr base::TaskTraits \
- LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyTraitsAreConstexpr, \
- __LINE__) = traits; \
- ALLOW_UNUSED_TYPE constexpr base::SingleThreadTaskRunnerThreadMode \
- LAZY_TASK_RUNNER_CONCATENATE_INTERNAL(kVerifyThreadModeIsConstexpr, \
- __LINE__) = thread_mode
- namespace internal {
- template <typename TaskRunnerType, bool com_sta>
- class BASE_EXPORT LazyThreadPoolTaskRunner {
- public:
- // Use the macros above rather than a direct call to this.
- //
- // |traits| are TaskTraits to use to create the TaskRunner. If this
- // LazyThreadPoolTaskRunner is specialized to create a SingleThreadTaskRunner,
- // |thread_mode| specifies whether the SingleThreadTaskRunner can share its
- // thread with other SingleThreadTaskRunner. Otherwise, it is unused.
- static constexpr LazyThreadPoolTaskRunner CreateInternal(
- const TaskTraits& traits,
- SingleThreadTaskRunnerThreadMode thread_mode =
- SingleThreadTaskRunnerThreadMode::SHARED) {
- return LazyThreadPoolTaskRunner(traits, thread_mode);
- }
- // Returns the TaskRunner held by this instance. Creates it if it didn't
- // already exist. Thread-safe.
- scoped_refptr<TaskRunnerType> Get();
- private:
- constexpr LazyThreadPoolTaskRunner(
- const TaskTraits& traits,
- SingleThreadTaskRunnerThreadMode thread_mode =
- SingleThreadTaskRunnerThreadMode::SHARED)
- : traits_(traits), thread_mode_(thread_mode) {}
- // Releases the TaskRunner held by this instance.
- void Reset();
- // Creates and returns a new TaskRunner.
- scoped_refptr<TaskRunnerType> Create();
- // Creates a new TaskRunner via Create(), adds an explicit ref to it, and
- // returns it raw. Used as an adapter for lazy instance helpers. Static and
- // takes |this| as an explicit param to match the void* signature of
- // GetOrCreateLazyPointer().
- static TaskRunnerType* CreateRaw(void* void_self);
- // TaskTraits to create the TaskRunner.
- const TaskTraits traits_;
- // SingleThreadTaskRunnerThreadMode to create the TaskRunner.
- const SingleThreadTaskRunnerThreadMode thread_mode_;
- // Can have 3 states:
- // - This instance does not hold a TaskRunner: 0
- // - This instance is creating a TaskRunner: kLazyInstanceStateCreating
- // - This instance holds a TaskRunner: Pointer to the TaskRunner.
- // LazyInstance's internals are reused to handle transition between states.
- subtle::AtomicWord state_ = 0;
- // No DISALLOW_COPY_AND_ASSIGN since that prevents static initialization with
- // Visual Studio (warning C4592: 'symbol will be dynamically initialized
- // (implementation limitation))'.
- };
- // When a LazyThreadPoolTaskRunner becomes active (invokes Get()), it adds a
- // callback to the current ScopedLazyTaskRunnerListForTesting, if any.
- // Callbacks run when the ScopedLazyTaskRunnerListForTesting is
- // destroyed. In a test process, a ScopedLazyTaskRunnerListForTesting
- // must be instantiated before any LazyThreadPoolTaskRunner becomes active.
- class BASE_EXPORT ScopedLazyTaskRunnerListForTesting {
- public:
- ScopedLazyTaskRunnerListForTesting();
- ~ScopedLazyTaskRunnerListForTesting();
- private:
- friend class LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
- friend class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
- #if defined(OS_WIN)
- friend class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
- #endif
- // Add |callback| to the list of callbacks to run on destruction.
- void AddCallback(OnceClosure callback);
- CheckedLock lock_;
- // List of callbacks to run on destruction.
- std::vector<OnceClosure> callbacks_ GUARDED_BY(lock_);
- DISALLOW_COPY_AND_ASSIGN(ScopedLazyTaskRunnerListForTesting);
- };
- } // namespace internal
- } // namespace base
- #endif // BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_
|