1 // Copyright 2020 The Pigweed Authors
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
7 // https://www.apache.org/licenses/LICENSE-2.0
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
19 #include "pw_chrono/system_clock.h"
20 #include "pw_sync/spin_lock.h"
22 namespace pw::chrono {
24 // A simulated system clock is a concrete virtual SystemClock implementation
25 // that does not "tick" on its own. Time is advanced by explicit calls to
26 // AdvanceTime() or SetTime() functions. This can be used as stub for testing
27 // which can be dependency injected. Be careful when using SetTime() to not
28 // violate the is_monotonic requirement, in other words avoid going backwards
29 // unless initializing the clock before consumers have a reference to the clock.
32 // SimulatedSystemClock sim_system_clock;
34 // SystemClock::time_point now = sim_system_clock.now();
35 // // now.time_since_epoch.duration() == std::chrono::seconds(0)
37 // sim_system_clock.AdvanceTime(std::chrono::seconds(42));
38 // // now.time_since_epoch.duration() == std::chrono::seconds(42)
40 // This code is thread & IRQ safe.
41 class SimulatedSystemClock : public VirtualSystemClock {
43 SimulatedSystemClock(SystemClock::time_point timestamp =
44 SystemClock::time_point(SystemClock::duration(0)))
45 : current_timestamp_(timestamp) {}
47 void AdvanceTime(SystemClock::duration duration) {
48 std::lock_guard lock(spin_lock_);
49 current_timestamp_ += duration;
52 // WARNING: Use of this function may violate the is_monotonic clock attribute.
53 void SetTime(SystemClock::time_point timestamp) {
54 std::lock_guard lock(spin_lock_);
55 current_timestamp_ = timestamp;
58 SystemClock::time_point now() override {
59 std::lock_guard lock(spin_lock_);
60 return current_timestamp_;
64 // In theory atomics could be used if 64bit atomics are supported, however
65 // performance of this test object shouldn't matter.
66 sync::SpinLock spin_lock_;
67 SystemClock::time_point current_timestamp_;
70 } // namespace pw::chrono