|  | // 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_SCHEDULER_LAZY_TASK_RUNNER_H_ | 
|  | #define BASE_TASK_SCHEDULER_LAZY_TASK_RUNNER_H_ | 
|  |  | 
|  | #include <vector> | 
|  |  | 
|  | #include "base/atomicops.h" | 
|  | #include "base/callback.h" | 
|  | #include "base/compiler_specific.h" | 
|  | #include "base/lazy_instance_helpers.h" | 
|  | #include "base/sequenced_task_runner.h" | 
|  | #include "base/single_thread_task_runner.h" | 
|  | #include "base/task_scheduler/scheduler_lock.h" | 
|  | #include "base/task_scheduler/single_thread_task_runner_thread_mode.h" | 
|  | #include "base/task_scheduler/task_traits.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 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 ScopedTaskEnvironment 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::Create(Sequenced|SingleThread|COMSTA)TaskRunnerWithTraits() as a member | 
|  | // on an object accessible by all PostTask() call sites. | 
|  | // | 
|  | // Example usage 1: | 
|  | // | 
|  | // namespace { | 
|  | // base::LazySequencedTaskRunner g_sequenced_task_runner = | 
|  | //     LAZY_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::LazySequencedTaskRunner g_sequenced_task_task_runner = | 
|  | //     LAZY_SEQUENCED_TASK_RUNNER_INITIALIZER({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 LazyTaskRunner; | 
|  | }  // namespace internal | 
|  |  | 
|  | // Lazy SequencedTaskRunner. | 
|  | using LazySequencedTaskRunner = | 
|  | internal::LazyTaskRunner<SequencedTaskRunner, false>; | 
|  |  | 
|  | // Lazy SingleThreadTaskRunner. | 
|  | using LazySingleThreadTaskRunner = | 
|  | internal::LazyTaskRunner<SingleThreadTaskRunner, false>; | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | // Lazy COM-STA enabled SingleThreadTaskRunner. | 
|  | using LazyCOMSTATaskRunner = | 
|  | internal::LazyTaskRunner<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 LazyTaskRunner. 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_SEQUENCED_TASK_RUNNER_INITIALIZER(traits)                 \ | 
|  | base::LazySequencedTaskRunner::CreateInternal(traits);               \ | 
|  | 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_SINGLE_THREAD_TASK_RUNNER_INITIALIZER(traits, thread_mode)   \ | 
|  | base::LazySingleThreadTaskRunner::CreateInternal(traits, thread_mode);  \ | 
|  | 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::LazyCOMSTATaskRunner::CreateInternal(traits, thread_mode);        \ | 
|  | 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 LazyTaskRunner { | 
|  | public: | 
|  | // Use the macros above rather than a direct call to this. | 
|  | // | 
|  | // |traits| are TaskTraits to use to create the TaskRunner. If this | 
|  | // LazyTaskRunner 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 LazyTaskRunner CreateInternal( | 
|  | const TaskTraits& traits, | 
|  | SingleThreadTaskRunnerThreadMode thread_mode = | 
|  | SingleThreadTaskRunnerThreadMode::SHARED) { | 
|  | return LazyTaskRunner(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 LazyTaskRunner(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 LazyTaskRunner 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 | 
|  | // LazyTaskRunner becomes active. | 
|  | class BASE_EXPORT ScopedLazyTaskRunnerListForTesting { | 
|  | public: | 
|  | ScopedLazyTaskRunnerListForTesting(); | 
|  | ~ScopedLazyTaskRunnerListForTesting(); | 
|  |  | 
|  | private: | 
|  | friend class LazyTaskRunner<SequencedTaskRunner, false>; | 
|  | friend class LazyTaskRunner<SingleThreadTaskRunner, false>; | 
|  |  | 
|  | #if defined(OS_WIN) | 
|  | friend class LazyTaskRunner<SingleThreadTaskRunner, true>; | 
|  | #endif | 
|  |  | 
|  | // Add |callback| to the list of callbacks to run on destruction. | 
|  | void AddCallback(OnceClosure callback); | 
|  |  | 
|  | // Synchronizes accesses to |callbacks_|. | 
|  | SchedulerLock lock_; | 
|  |  | 
|  | // List of callbacks to run on destruction. | 
|  | std::vector<OnceClosure> callbacks_; | 
|  |  | 
|  | DISALLOW_COPY_AND_ASSIGN(ScopedLazyTaskRunnerListForTesting); | 
|  | }; | 
|  |  | 
|  | }  // namespace internal | 
|  | }  // namespace base | 
|  |  | 
|  | #endif  // BASE_TASK_SCHEDULER_LAZY_TASK_RUNNER_H_ |