mirror of
https://github.com/klzgrad/naiveproxy.git
synced 2024-12-01 01:36:09 +03:00
213 lines
8.4 KiB
C
213 lines
8.4 KiB
C
|
// 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.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();
|
||
|
|
||
|
// 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_
|