forked from chromium/chromium
-
Notifications
You must be signed in to change notification settings - Fork 0
/
chromeos_delayed_callback_group.cc
115 lines (100 loc) · 3.77 KB
/
chromeos_delayed_callback_group.cc
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
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();
}
}