// Copyright 2017 The Chromium Authors // 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 <atomic> #include <vector> #include "base/base_export.h" #include "base/functional/callback.h" #include "base/macros/uniquify.h" #include "base/task/common/checked_lock.h" #include "base/task/sequenced_task_runner.h" #include "base/task/single_thread_task_runner.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. LazyThreadPoolSequencedTaskRunner; // Lazy SingleThreadTaskRunner. LazyThreadPoolSingleThreadTaskRunner; #if BUILDFLAG(IS_WIN) // Lazy COM-STA enabled SingleThreadTaskRunner. using LazyThreadPoolCOMSTATaskRunner = internal::LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>; #endif // 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) … // |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) … // |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) … namespace internal { template <typename TaskRunnerType, bool com_sta> class BASE_EXPORT LazyThreadPoolTaskRunner { … }; // 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 { … }; } // namespace internal } // namespace base #endif // BASE_TASK_LAZY_THREAD_POOL_TASK_RUNNER_H_