diff options
Diffstat (limited to 'chromium/chrome/renderer/chromeos_delayed_callback_group.cc')
-rw-r--r-- | chromium/chrome/renderer/chromeos_delayed_callback_group.cc | 115 |
1 files changed, 115 insertions, 0 deletions
diff --git a/chromium/chrome/renderer/chromeos_delayed_callback_group.cc b/chromium/chrome/renderer/chromeos_delayed_callback_group.cc new file mode 100644 index 00000000000..8ce4700e5c0 --- /dev/null +++ b/chromium/chrome/renderer/chromeos_delayed_callback_group.cc @@ -0,0 +1,115 @@ +// Copyright 2019 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 "chrome/renderer/chromeos_delayed_callback_group.h" + +#include <utility> + +#include "base/task/post_task.h" +#include "base/bind.h" +#include "base/threading/sequenced_task_runner_handle.h" +#include "base/threading/thread_task_runner_handle.h" + +DelayedCallbackGroup::CallbackEntry::CallbackEntry( + Callback callback, + const scoped_refptr<base::SequencedTaskRunner> callback_task_runner, + base::TimeTicks expiration_time) + : callback_(std::move(callback)), + callback_task_runner_(std::move(callback_task_runner)), + expiration_time_(expiration_time) {} + +DelayedCallbackGroup::CallbackEntry::~CallbackEntry() {} + +DelayedCallbackGroup::DelayedCallbackGroup( + base::TimeDelta expiration_delay, + scoped_refptr<base::SequencedTaskRunner> expiration_task_runner) + : expiration_delay_(expiration_delay), + expiration_task_runner_(expiration_task_runner) { + DETACH_FROM_SEQUENCE(sequence_checker_); +} + +DelayedCallbackGroup::~DelayedCallbackGroup() { + base::AutoLock lock(callbacks_lock_); + CancelExpirationTimer(); + ExpireAllCallbacks(); +} + +void DelayedCallbackGroup::Add(Callback callback) { + DCHECK(base::SequencedTaskRunnerHandle::IsSet()); + { + base::AutoLock lock(callbacks_lock_); + base::TimeTicks expiration_time = + base::TimeTicks::Now() + expiration_delay_; + callbacks_.emplace(std::move(callback), + base::SequencedTaskRunnerHandle::Get(), expiration_time); + } + expiration_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(&DelayedCallbackGroup::StartExpirationTimer, this)); +} + +void DelayedCallbackGroup::CancelExpirationTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + expiration_timeout_.Cancel(); +} + +void DelayedCallbackGroup::StartExpirationTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::AutoLock lock(callbacks_lock_); + if (callbacks_.empty() || !expiration_timeout_.IsCancelled()) + return; + + base::TimeDelta delay_until_next_expiration = + callbacks_.front().expiration_time_ - base::TimeTicks::Now(); + expiration_timeout_.Reset( + base::BindOnce(&DelayedCallbackGroup::OnExpirationTimer, this)); + expiration_task_runner_->PostDelayedTask( + FROM_HERE, expiration_timeout_.callback(), delay_until_next_expiration); +} + +void DelayedCallbackGroup::OnExpirationTimer() { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + ProcessExpiredCallbacks(base::TimeTicks::Now()); + StartExpirationTimer(); +} + +void DelayedCallbackGroup::RunAll() { + base::AutoLock lock(callbacks_lock_); + while (!callbacks_.empty()) { + CallbackEntry& entry = callbacks_.front(); + entry.callback_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(entry.callback_), RunReason::NORMAL)); + callbacks_.pop(); + } +} + +void DelayedCallbackGroup::ProcessExpiredCallbacks( + base::TimeTicks expiration_time) { + DCHECK_CALLED_ON_VALID_SEQUENCE(sequence_checker_); + base::AutoLock lock(callbacks_lock_); + CancelExpirationTimer(); + while (!callbacks_.empty()) { + CallbackEntry& entry = callbacks_.front(); + if (entry.expiration_time_ <= expiration_time) { + entry.callback_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(entry.callback_), RunReason::TIMEOUT)); + callbacks_.pop(); + } else { + // All others in this queue expire after |expiration_time|. + return; + } + } +} + +void DelayedCallbackGroup::ExpireAllCallbacks() { + while (!callbacks_.empty()) { + CallbackEntry& entry = callbacks_.front(); + entry.callback_task_runner_->PostTask( + FROM_HERE, + base::BindOnce(std::move(entry.callback_), RunReason::TIMEOUT)); + callbacks_.pop(); + } +} |