1 /*
2 * Copyright (c) 2020 The WebRTC project authors. All Rights Reserved.
3 *
4 * Use of this source code is governed by a BSD-style license
5 * that can be found in the LICENSE file in the root of the source
6 * tree. An additional intellectual property rights grant can be found
7 * in the file PATENTS. All contributing project authors may
8 * be found in the AUTHORS file in the root of the source tree.
9 */
10 #include "test/time_controller/simulated_task_queue.h"
11
12 #include <algorithm>
13 #include <utility>
14
15 namespace webrtc {
16
SimulatedTaskQueue(sim_time_impl::SimulatedTimeControllerImpl * handler,absl::string_view name)17 SimulatedTaskQueue::SimulatedTaskQueue(
18 sim_time_impl::SimulatedTimeControllerImpl* handler,
19 absl::string_view name)
20 : handler_(handler), name_(new char[name.size()]) {
21 std::copy_n(name.begin(), name.size(), name_);
22 }
23
~SimulatedTaskQueue()24 SimulatedTaskQueue::~SimulatedTaskQueue() {
25 handler_->Unregister(this);
26 delete[] name_;
27 }
28
Delete()29 void SimulatedTaskQueue::Delete() {
30 // Need to destroy the tasks outside of the lock because task destruction
31 // can lead to re-entry in SimulatedTaskQueue via custom destructors.
32 std::deque<absl::AnyInvocable<void() &&>> ready_tasks;
33 std::map<Timestamp, std::vector<absl::AnyInvocable<void() &&>>> delayed_tasks;
34 {
35 MutexLock lock(&lock_);
36 ready_tasks_.swap(ready_tasks);
37 delayed_tasks_.swap(delayed_tasks);
38 }
39 ready_tasks.clear();
40 delayed_tasks.clear();
41 delete this;
42 }
43
RunReady(Timestamp at_time)44 void SimulatedTaskQueue::RunReady(Timestamp at_time) {
45 MutexLock lock(&lock_);
46 for (auto it = delayed_tasks_.begin();
47 it != delayed_tasks_.end() && it->first <= at_time;
48 it = delayed_tasks_.erase(it)) {
49 for (auto& task : it->second) {
50 ready_tasks_.push_back(std::move(task));
51 }
52 }
53 CurrentTaskQueueSetter set_current(this);
54 while (!ready_tasks_.empty()) {
55 absl::AnyInvocable<void()&&> ready = std::move(ready_tasks_.front());
56 ready_tasks_.pop_front();
57 lock_.Unlock();
58 std::move(ready)();
59 ready = nullptr;
60 lock_.Lock();
61 }
62 if (!delayed_tasks_.empty()) {
63 next_run_time_ = delayed_tasks_.begin()->first;
64 } else {
65 next_run_time_ = Timestamp::PlusInfinity();
66 }
67 }
68
PostTask(absl::AnyInvocable<void ()&&> task)69 void SimulatedTaskQueue::PostTask(absl::AnyInvocable<void() &&> task) {
70 MutexLock lock(&lock_);
71 ready_tasks_.push_back(std::move(task));
72 next_run_time_ = Timestamp::MinusInfinity();
73 }
74
PostDelayedTask(absl::AnyInvocable<void ()&&> task,TimeDelta delay)75 void SimulatedTaskQueue::PostDelayedTask(absl::AnyInvocable<void() &&> task,
76 TimeDelta delay) {
77 PostDelayedHighPrecisionTask(std::move(task), delay);
78 }
79
PostDelayedHighPrecisionTask(absl::AnyInvocable<void ()&&> task,TimeDelta delay)80 void SimulatedTaskQueue::PostDelayedHighPrecisionTask(
81 absl::AnyInvocable<void() &&> task,
82 TimeDelta delay) {
83 MutexLock lock(&lock_);
84 Timestamp target_time = handler_->CurrentTime() + delay;
85 delayed_tasks_[target_time].push_back(std::move(task));
86 next_run_time_ = std::min(next_run_time_, target_time);
87 }
88
89 } // namespace webrtc
90