-
Notifications
You must be signed in to change notification settings - Fork 1
Expand file tree
/
Copy pathTimer.hpp
More file actions
114 lines (95 loc) · 2.64 KB
/
Copy pathTimer.hpp
File metadata and controls
114 lines (95 loc) · 2.64 KB
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
#pragma once
#include <cstdint>
#include <cstdio>
#include <climits>
#include <map>
#include <deque>
#include <chrono>
#include <limits>
#include "Logger.hpp"
#include "Debug.hpp"
struct Timer {
using time_t = double;
using key_t = uint32_t;
static constexpr key_t CURRENT_TIME = std::numeric_limits<key_t>::max();
static constexpr time_t time_start() {
return .0;
}
static time_t system_time() {
static std::mutex mtx;
static auto systime_start = std::chrono::system_clock::now();
std::lock_guard<std::mutex> guard(mtx);
auto systime_now = std::chrono::system_clock::now();
return 1e-9 * std::chrono::duration_cast<std::chrono::nanoseconds>(systime_now - systime_start).count();
}
time_t prev_time = time_start();
time_t current_time = time_start();
std::map<key_t, time_t> events;
std::map<key_t, std::deque<time_t>> event_counters;
std::map<key_t, time_t> timeouts;
Timer()
{}
/* void dump_times() { */
/* for(const auto &[k,t] : events){Logger::Info("%d: %f\n",k,t);} */
/* } */
void set_time(time_t curtime) {
prev_time = current_time;
current_time = curtime;
}
void set_event(key_t key) {
ASSERT(key != CURRENT_TIME);
events[key] = current_time;
}
time_t elapsed(key_t key=CURRENT_TIME) const {
/* Logger::Info("elapsed access: %d\n", key); */
if(key == CURRENT_TIME)return current_time - prev_time;
return current_time - events.at(key);
}
void set_event_counter(key_t key) {
event_counters[key].push_back(key);
}
time_t difference(key_t key) const {
return event_counters.at(key).back() - event_counters.at(key).front();
}
int get_count(key_t key) {
while(difference(key) > timeouts[key]) {
event_counters[key].pop_front();
}
return event_counters[key].size();
}
void set_timeout(key_t key, time_t timeout) {
if(events.find(key) == events.end()) {
set_event(key);
}
timeouts[key] = timeout;
}
bool timed_out(key_t key) const {
/* Logger::Info("timeout access: %d\n", key); */
time_t timeout = .0;
if(events.find(key) == events.end()) {
return true;
}
if(timeouts.find(key) != timeouts.end()) {
timeout = timeouts.at(key);
}
return elapsed(key) > timeout;
}
template <typename F>
void periodic(key_t key, F &&func) {
if(timed_out(key)) {
set_event(key);
func();
}
}
void erase(key_t key) {
if(events.find(key) != events.end()) {
events.erase(key);
}
if(event_counters.find(key) != event_counters.end()) {
event_counters.erase(key);
}
if(timeouts.find(key) != timeouts.end()) {
timeouts.erase(key);
}
}
};