| Index: base/task_scheduler/shutdown_manager.cc
|
| diff --git a/base/task_scheduler/shutdown_manager.cc b/base/task_scheduler/shutdown_manager.cc
|
| new file mode 100644
|
| index 0000000000000000000000000000000000000000..61805b38be97917ab2e1dee357c5367aeb9e6aca
|
| --- /dev/null
|
| +++ b/base/task_scheduler/shutdown_manager.cc
|
| @@ -0,0 +1,104 @@
|
| +// Copyright 2016 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_scheduler/shutdown_manager.h"
|
| +
|
| +#include "base/atomicops.h"
|
| +
|
| +namespace base {
|
| +namespace internal {
|
| +
|
| +ShutdownManager::ShutdownManager()
|
| + : cv_(lock_.RawLockForConditionVariable()),
|
| + num_tasks_blocking_shutdown_(0),
|
| + is_shutting_down_(false),
|
| + shutdown_completed_(false) {
|
| + subtle::MemoryBarrier();
|
| +}
|
| +
|
| +void ShutdownManager::Shutdown() {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| +
|
| + DCHECK(!is_shutting_down_) << "ShutdownManager::Shutdown can't be called "
|
| + "simultaneously on multiple threads.";
|
| + is_shutting_down_ = true;
|
| +
|
| + // Wait until the number of tasks blocking shutdown is zero.
|
| + while (num_tasks_blocking_shutdown_ != 0)
|
| + cv_.Wait();
|
| +
|
| + is_shutting_down_ = false;
|
| + shutdown_completed_ = true;
|
| +}
|
| +
|
| +bool ShutdownManager::ShouldPostTask(TaskShutdownBehavior shutdown_behavior) {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| +
|
| + if (shutdown_completed_)
|
| + return false;
|
| +
|
| + if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN) {
|
| + ++num_tasks_blocking_shutdown_;
|
| + return true;
|
| + }
|
| +
|
| + return !is_shutting_down_;
|
| +}
|
| +
|
| +bool ShutdownManager::ShouldScheduleTask(
|
| + TaskShutdownBehavior shutdown_behavior) {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| +
|
| + if (shutdown_completed_)
|
| + return false;
|
| +
|
| + switch (shutdown_behavior) {
|
| + case TaskShutdownBehavior::BLOCK_SHUTDOWN: {
|
| + return true;
|
| + }
|
| +
|
| + case TaskShutdownBehavior::SKIP_ON_SHUTDOWN: {
|
| + if (is_shutting_down_)
|
| + return false;
|
| + ++num_tasks_blocking_shutdown_;
|
| + return true;
|
| + }
|
| +
|
| + case TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN: {
|
| + return !is_shutting_down_;
|
| + }
|
| +
|
| + default: {
|
| + NOTREACHED();
|
| + return false;
|
| + }
|
| + }
|
| +}
|
| +
|
| +void ShutdownManager::DidExecuteTask(TaskShutdownBehavior shutdown_behavior) {
|
| + if (shutdown_behavior == TaskShutdownBehavior::BLOCK_SHUTDOWN ||
|
| + shutdown_behavior == TaskShutdownBehavior::SKIP_ON_SHUTDOWN) {
|
| + AutoSchedulerLock auto_lock(lock_);
|
| + --num_tasks_blocking_shutdown_;
|
| + if (num_tasks_blocking_shutdown_ == 0)
|
| + cv_.Signal();
|
| + }
|
| +}
|
| +
|
| +void ShutdownManager::set_is_shutting_down_for_testing(bool is_shutting_down) {
|
| + is_shutting_down_ = is_shutting_down;
|
| +}
|
| +
|
| +bool ShutdownManager::is_shutting_down_for_testing() const {
|
| + subtle::MemoryBarrier();
|
| + return is_shutting_down_;
|
| +}
|
| +
|
| +bool ShutdownManager::shutdown_completed() const {
|
| + subtle::MemoryBarrier();
|
| + return shutdown_completed_;
|
| +}
|
| +
|
| +} // namespace internal
|
| +} // namespace base
|
|
|