123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127 |
- // 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.
- #include "base/task/lazy_thread_pool_task_runner.h"
- #include <atomic>
- #include <utility>
- #include "base/check_op.h"
- #include "base/lazy_instance_helpers.h"
- #include "base/task/thread_pool.h"
- #include "build/build_config.h"
- namespace base {
- namespace internal {
- namespace {
- ScopedLazyTaskRunnerListForTesting* g_scoped_lazy_task_runner_list_for_testing =
- nullptr;
- } // namespace
- template <typename TaskRunnerType, bool com_sta>
- void LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::Reset() {
- uintptr_t state = state_.load(std::memory_order_acquire);
- DCHECK_NE(state, kLazyInstanceStateCreating) << "Race: all threads should be "
- "unwound in unittests before "
- "resetting TaskRunners.";
- // Return if no reference is held by this instance.
- if (!state)
- return;
- // Release the reference acquired in Get().
- SequencedTaskRunner* task_runner = reinterpret_cast<TaskRunnerType*>(state);
- task_runner->Release();
- // Clear the state.
- state_.store(0, std::memory_order_relaxed);
- }
- template <>
- scoped_refptr<SequencedTaskRunner>
- LazyThreadPoolTaskRunner<SequencedTaskRunner, false>::Create() {
- // It is invalid to specify a SingleThreadTaskRunnerThreadMode with a
- // LazyThreadPoolSequencedTaskRunner.
- DCHECK_EQ(thread_mode_, SingleThreadTaskRunnerThreadMode::SHARED);
- return ThreadPool::CreateSequencedTaskRunner(traits_);
- }
- template <>
- scoped_refptr<SingleThreadTaskRunner>
- LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>::Create() {
- return ThreadPool::CreateSingleThreadTaskRunner(traits_, thread_mode_);
- }
- #if BUILDFLAG(IS_WIN)
- template <>
- scoped_refptr<SingleThreadTaskRunner>
- LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>::Create() {
- return ThreadPool::CreateCOMSTATaskRunner(traits_, thread_mode_);
- }
- #endif
- // static
- template <typename TaskRunnerType, bool com_sta>
- TaskRunnerType* LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::CreateRaw(
- void* void_self) {
- auto self =
- reinterpret_cast<LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>*>(
- void_self);
- scoped_refptr<TaskRunnerType> task_runner = self->Create();
- // Acquire a reference to the TaskRunner. The reference will either
- // never be released or be released in Reset(). The reference is not
- // managed by a scoped_refptr because adding a scoped_refptr member to
- // LazyThreadPoolTaskRunner would prevent its static initialization.
- task_runner->AddRef();
- // Reset this instance when the current
- // ScopedLazyTaskRunnerListForTesting is destroyed, if any.
- if (g_scoped_lazy_task_runner_list_for_testing) {
- g_scoped_lazy_task_runner_list_for_testing->AddCallback(
- BindOnce(&LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::Reset,
- Unretained(self)));
- }
- return task_runner.get();
- }
- template <typename TaskRunnerType, bool com_sta>
- scoped_refptr<TaskRunnerType>
- LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::Get() {
- return WrapRefCounted(subtle::GetOrCreateLazyPointer(
- state_, &LazyThreadPoolTaskRunner<TaskRunnerType, com_sta>::CreateRaw,
- reinterpret_cast<void*>(this), nullptr, nullptr));
- }
- template class LazyThreadPoolTaskRunner<SequencedTaskRunner, false>;
- template class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, false>;
- #if BUILDFLAG(IS_WIN)
- template class LazyThreadPoolTaskRunner<SingleThreadTaskRunner, true>;
- #endif
- ScopedLazyTaskRunnerListForTesting::ScopedLazyTaskRunnerListForTesting() {
- DCHECK(!g_scoped_lazy_task_runner_list_for_testing);
- g_scoped_lazy_task_runner_list_for_testing = this;
- }
- ScopedLazyTaskRunnerListForTesting::~ScopedLazyTaskRunnerListForTesting() {
- internal::CheckedAutoLock auto_lock(lock_);
- for (auto& callback : callbacks_)
- std::move(callback).Run();
- g_scoped_lazy_task_runner_list_for_testing = nullptr;
- }
- void ScopedLazyTaskRunnerListForTesting::AddCallback(OnceClosure callback) {
- internal::CheckedAutoLock auto_lock(lock_);
- callbacks_.push_back(std::move(callback));
- }
- } // namespace internal
- } // namespace base
|