C/C++ API Reference
Loading...
Searching...
No Matches
simulated_time_provider.h
1// Copyright 2024 The Pigweed Authors
2//
3// Licensed under the Apache License, Version 2.0 (the "License"); you may not
4// use this file except in compliance with the License. You may obtain a copy of
5// the License at
6//
7// https://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
11// WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12// License for the specific language governing permissions and limitations under
13// the License.
14
15#pragma once
16
17#include "pw_async2/time_provider.h"
18#include "pw_sync/interrupt_spin_lock.h"
19
20namespace pw::async2 {
21
23
25template <typename Clock>
26class SimulatedTimeProvider final : public TimeProvider<Clock> {
27 public:
29 typename Clock::time_point timestamp =
30 typename Clock::time_point(typename Clock::duration(0)))
31 : now_(timestamp) {}
32
34 void AdvanceTime(typename Clock::duration duration) {
35 lock_.lock();
36 SetTimeUnlockAndRun(now_ + duration);
37 }
38
44 lock_.lock();
45 if (next_wake_time_ == std::nullopt) {
46 lock_.unlock();
47 return false;
48 }
49 SetTimeUnlockAndRun(*next_wake_time_);
50 return true;
51 }
52
58 void SetTime(typename Clock::time_point new_now) {
59 lock_.lock();
60 SetTimeUnlockAndRun(new_now);
61 }
62
71
72 typename Clock::time_point now() final {
73 std::lock_guard lock(lock_);
74 return now_;
75 }
76
77 std::optional<typename Clock::time_point> NextExpiration() {
78 std::lock_guard lock(lock_);
79 return next_wake_time_;
80 }
81
82 std::optional<typename Clock::duration> TimeUntilNextExpiration() {
83 std::lock_guard lock(lock_);
84 if (next_wake_time_ == std::nullopt) {
85 return std::nullopt;
86 }
87 return *next_wake_time_ - now_;
88 }
89
90 private:
91 void SetTimeUnlockAndRun(typename Clock::time_point new_now)
92 PW_UNLOCK_FUNCTION(lock_) {
93 now_ = new_now;
94 if (new_now >= next_wake_time_) {
95 next_wake_time_ = std::nullopt;
96 lock_.unlock();
98 } else {
99 lock_.unlock();
100 }
101 }
102
103 void DoInvokeAt(typename Clock::time_point wake_time) final {
104 std::lock_guard lock(lock_);
105 next_wake_time_ = wake_time;
106
107 // We don't need to actually schedule anything here since calls to
108 // `RunExpired` are triggered directly by user calls to
109 // `AdvanceTime`/`SetTime`.
110 //
111 // Note: we cannot run the timer here even if it was in the past because
112 // `DoInvokeAt` is called under `TimeProvider`'s lock. Furthermore, we
113 // might be *inside* the current callback due to a nested invocation of
114 // `InvokeAfter`/`InvokeAt`.
115 }
116
117 void DoCancel() final {
118 std::lock_guard lock(lock_);
119 next_wake_time_ = std::nullopt;
120
121 // We don't need to do anything here since `RunExpired` itself is safe to
122 // call redundantly-- it will filter out extra invocations.
123 }
124
125 mutable sync::InterruptSpinLock lock_;
126 typename Clock::time_point now_ PW_GUARDED_BY(lock_);
127 std::optional<typename Clock::time_point> next_wake_time_
128 PW_GUARDED_BY(lock_);
129};
130
132
133} // namespace pw::async2
A simulated TimeProvider suitable for testing APIs which use Timer.
Definition: simulated_time_provider.h:26
bool AdvanceUntilNextExpiration()
Definition: simulated_time_provider.h:43
void RunExpiredTimers()
Definition: simulated_time_provider.h:70
void AdvanceTime(typename Clock::duration duration)
Advances the simulated time and runs any newly-expired timers.
Definition: simulated_time_provider.h:34
void DoInvokeAt(typename Clock::time_point wake_time) final
Definition: simulated_time_provider.h:103
void DoCancel() final
Optimistically cancels all pending DoInvokeAt requests.
Definition: simulated_time_provider.h:117
void SetTime(typename Clock::time_point new_now)
Definition: simulated_time_provider.h:58
Clock::time_point now() final
Returns the current time.
Definition: simulated_time_provider.h:72
Definition: time_provider.h:62
Definition: interrupt_spin_lock.h:50
void RunExpired(typename Clock::time_point now)
Definition: time_provider.h:275
#define PW_GUARDED_BY(x)
Definition: lock_annotations.h:60
#define PW_UNLOCK_FUNCTION(...)
Definition: lock_annotations.h:247