forked from envoyproxy/envoy
-
Notifications
You must be signed in to change notification settings - Fork 1
/
simulated_time_system.h
142 lines (118 loc) · 4.76 KB
/
simulated_time_system.h
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
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
#pragma once
#include "envoy/event/timer.h"
#include "source/common/common/lock_guard.h"
#include "source/common/common/thread.h"
#include "test/test_common/test_random_generator.h"
#include "test/test_common/test_time_system.h"
#include "test/test_common/thread_factory_for_test.h"
#include "absl/container/flat_hash_map.h"
namespace Envoy {
namespace Event {
// Implements a simulated time system including a scheduler for timers. This is
// designed to be used as the exclusive time-system resident in a process at
// any particular time, and as such should not be instantiated directly by
// tests. Instead it should be instantiated via SimulatedTimeSystem, declared
// below.
class SimulatedTimeSystemHelper : public TestTimeSystem {
public:
SimulatedTimeSystemHelper();
~SimulatedTimeSystemHelper() override;
// TimeSystem
SchedulerPtr createScheduler(Scheduler& base_scheduler, CallbackScheduler& cb_scheduler) override;
// TestTimeSystem
void advanceTimeWaitImpl(const Duration& duration) override;
void advanceTimeAsyncImpl(const Duration& duration) override;
// TimeSource
SystemTime systemTime() override;
MonotonicTime monotonicTime() override;
/**
* Sets the time forward monotonically. If the supplied argument moves
* backward in time, the call is a no-op. If the supplied argument moves
* forward, any applicable timers are fired, and system-time is also moved
* forward by the same delta.
*
* @param monotonic_time The desired new current time.
*/
void setMonotonicTime(const MonotonicTime& monotonic_time) {
absl::MutexLock lock(&mutex_);
setMonotonicTimeLockHeld(monotonic_time);
}
/**
* Sets the system-time, whether forward or backward. If time moves forward,
* applicable timers are fired and monotonic time is also increased by the
* same delta.
*
* @param system_time The desired new system time.
*/
void setSystemTime(const SystemTime& system_time);
static bool hasInstance();
private:
class SimulatedScheduler;
class Alarm;
void registerScheduler(SimulatedScheduler* scheduler) {
absl::MutexLock lock(&mutex_);
schedulers_.insert(scheduler);
}
void unregisterScheduler(SimulatedScheduler* scheduler) {
absl::MutexLock lock(&mutex_);
schedulers_.erase(scheduler);
}
/**
* Sets the time forward monotonically. If the supplied argument moves
* backward in time, the call is a no-op. If the supplied argument moves
* forward, any applicable timers are fired, and system-time is also moved
* forward by the same delta.
*
* @param monotonic_time The desired new current time.
*/
void setMonotonicTimeLockHeld(const MonotonicTime& monotonic_time)
ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
// Keeps track of the number of simulated schedulers that have pending monotonic time updates.
// Used by advanceTimeWait() to determine when the time updates have finished propagating.
void incPending() {
absl::MutexLock lock(&mutex_);
++pending_updates_;
}
void decPending() {
absl::MutexLock lock(&mutex_);
--pending_updates_;
}
void waitForNoPendingLockHeld() const ABSL_EXCLUSIVE_LOCKS_REQUIRED(mutex_);
void maybeLogTimerWarning();
RealTimeSource real_time_source_; // Used to initialize monotonic_time_ and system_time_;
MonotonicTime monotonic_time_ ABSL_GUARDED_BY(mutex_);
SystemTime system_time_ ABSL_GUARDED_BY(mutex_);
TestRandomGenerator random_source_ ABSL_GUARDED_BY(mutex_);
std::set<SimulatedScheduler*> schedulers_ ABSL_GUARDED_BY(mutex_);
mutable absl::Mutex mutex_;
uint32_t pending_updates_ ABSL_GUARDED_BY(mutex_){0};
std::atomic<uint32_t> warning_logged_{};
};
// Represents a simulated time system, where time is advanced by calling
// sleep(), setSystemTime(), or setMonotonicTime(). systemTime() and
// monotonicTime() are maintained in the class, and alarms are fired in response
// to adjustments in time.
class SimulatedTimeSystem : public DelegatingTestTimeSystem<SimulatedTimeSystemHelper> {
public:
void setMonotonicTime(const MonotonicTime& monotonic_time) {
timeSystem().setMonotonicTime(monotonic_time);
}
void setSystemTime(const SystemTime& system_time) { timeSystem().setSystemTime(system_time); }
template <class Duration> void setMonotonicTime(const Duration& duration) {
setMonotonicTime(MonotonicTime(duration));
}
template <class Duration> void setSystemTime(const Duration& duration) {
setSystemTime(SystemTime(duration));
}
};
// Class encapsulating a SimulatedTimeSystem, intended for integration tests.
// Inherit from this mixin in a test fixture class to use a SimulatedTimeSystem
// during the test.
class TestUsingSimulatedTime {
public:
SimulatedTimeSystem& simTime() { return sim_time_; }
private:
SimulatedTimeSystem sim_time_;
};
} // namespace Event
} // namespace Envoy