Pigweed
 
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
23template <typename Clock>
24class SimulatedTimeProvider final : public TimeProvider<Clock> {
25 public:
27 typename Clock::time_point timestamp =
28 typename Clock::time_point(typename Clock::duration(0)))
29 : now_(timestamp) {}
30
32 void AdvanceTime(typename Clock::duration duration) {
33 lock_.lock();
34 SetTimeUnlockAndRun(now_ + duration);
35 }
36
42 lock_.lock();
43 if (next_wake_time_ == std::nullopt) {
44 lock_.unlock();
45 return false;
46 }
47 SetTimeUnlockAndRun(*next_wake_time_);
48 return true;
49 }
50
56 void SetTime(typename Clock::time_point new_now) {
57 lock_.lock();
58 SetTimeUnlockAndRun(new_now);
59 }
60
69
70 typename Clock::time_point now() final {
71 std::lock_guard lock(lock_);
72 return now_;
73 }
74
75 std::optional<typename Clock::time_point> NextExpiration() {
76 std::lock_guard lock(lock_);
77 return next_wake_time_;
78 }
79
80 std::optional<typename Clock::duration> TimeUntilNextExpiration() {
81 std::lock_guard lock(lock_);
82 if (next_wake_time_ == std::nullopt) {
83 return std::nullopt;
84 }
85 return *next_wake_time_ - now_;
86 }
87
88 private:
89 void SetTimeUnlockAndRun(typename Clock::time_point new_now)
90 PW_UNLOCK_FUNCTION(lock_) {
91 now_ = new_now;
92 if (new_now >= next_wake_time_) {
93 next_wake_time_ = std::nullopt;
94 lock_.unlock();
96 } else {
97 lock_.unlock();
98 }
99 }
100
101 void DoInvokeAt(typename Clock::time_point wake_time) final {
102 std::lock_guard lock(lock_);
103 next_wake_time_ = wake_time;
104
105 // We don't need to actually schedule anything here since calls to
106 // `RunExpired` are triggered directly by user calls to
107 // `AdvanceTime`/`SetTime`.
108 //
109 // Note: we cannot run the timer here even if it was in the past because
110 // `DoInvokeAt` is called under `TimeProvider`'s lock. Furthermore, we
111 // might be *inside* the current callback due to a nested invocation of
112 // `InvokeAfter`/`InvokeAt`.
113 }
114
115 void DoCancel() final {
116 std::lock_guard lock(lock_);
117 next_wake_time_ = std::nullopt;
118
119 // We don't need to do anything here since `RunExpired` itself is safe to
120 // call redundantly-- it will filter out extra invocations.
121 }
122
123 mutable sync::InterruptSpinLock lock_;
124 typename Clock::time_point now_ PW_GUARDED_BY(lock_);
125 std::optional<typename Clock::time_point> next_wake_time_
126 PW_GUARDED_BY(lock_);
127};
128
129} // namespace pw::async2
A simulated TimeProvider suitable for testing APIs which use Timer.
Definition: simulated_time_provider.h:24
bool AdvanceUntilNextExpiration()
Definition: simulated_time_provider.h:41
void RunExpiredTimers()
Definition: simulated_time_provider.h:68
void AdvanceTime(typename Clock::duration duration)
Advances the simulated time and runs any newly-expired timers.
Definition: simulated_time_provider.h:32
void DoInvokeAt(typename Clock::time_point wake_time) final
Definition: simulated_time_provider.h:101
void DoCancel() final
Optimistically cancels all pending DoInvokeAt requests.
Definition: simulated_time_provider.h:115
void SetTime(typename Clock::time_point new_now)
Definition: simulated_time_provider.h:56
Clock::time_point now() final
Returns the current time.
Definition: simulated_time_provider.h:70
Definition: time_provider.h:60
void RunExpired(typename Clock::time_point now)
Definition: time_provider.h:273
Definition: interrupt_spin_lock.h:48