blob: dc5967c7efc85f9bcd1cc3eb0b9798b2030070b1 [file] [log] [blame]
Austin Schuh2dc8c7d2021-07-01 17:41:28 -07001#ifndef AOS_EVENTS_LOGGING_BOOT_TIMESTAMP_H_
2#define AOS_EVENTS_LOGGING_BOOT_TIMESTAMP_H_
3
Stephan Pleines5ecc8f12024-05-31 20:35:21 -07004#include <stddef.h>
5#include <stdint.h>
6
7#include <chrono>
8#include <compare>
Austin Schuh2dc8c7d2021-07-01 17:41:28 -07009#include <iostream>
Stephan Pleines5ecc8f12024-05-31 20:35:21 -070010#include <limits>
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070011
Austin Schuh704784e2022-07-13 21:11:41 -070012#include "glog/logging.h"
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070013
Philipp Schrader790cb542023-07-05 21:06:52 -070014#include "aos/time/time.h"
15
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070016namespace aos::logger {
17
Austin Schuh66168842021-08-17 19:42:21 -070018// Simple class representing a duration in time and a boot it is from. This
19// gives us something to use for storing the time offset when filtering.
20struct BootDuration {
21 // Boot number for this timestamp.
22 size_t boot = 0u;
23 // Monotonic time in that boot.
24 monotonic_clock::duration duration{0};
25
26 BootDuration operator+(monotonic_clock::duration d) const {
27 return {boot, duration + d};
28 }
29
Austin Schuhefba96d2022-06-24 13:22:18 -070030 BootDuration operator-() const { return {boot, -duration}; }
31 BootDuration operator-(monotonic_clock::duration d) const {
32 return {boot, duration - d};
33 }
34
Austin Schuh704784e2022-07-13 21:11:41 -070035 BootDuration operator-(BootDuration d) const {
36 CHECK_EQ(d.boot, boot);
37 return {boot, duration - d.duration};
38 }
39
40 BootDuration operator+(BootDuration d) const {
41 CHECK_EQ(d.boot, boot);
42 return {boot, duration + d.duration};
43 }
44
45 BootDuration operator/(int x) const { return {boot, duration / x}; }
46
Austin Schuh66168842021-08-17 19:42:21 -070047 bool operator==(const BootDuration &m2) const {
48 return boot == m2.boot && duration == m2.duration;
49 }
Austin Schuhc1ee1b62022-03-22 17:09:52 -070050 bool operator!=(const BootDuration &m2) const {
51 return boot != m2.boot || duration != m2.duration;
52 }
53
54 static constexpr BootDuration max_time() {
55 return BootDuration{
56 .boot = std::numeric_limits<size_t>::max(),
57 .duration = monotonic_clock::duration(
58 ::std::numeric_limits<monotonic_clock::duration::rep>::max())};
59 }
Austin Schuh66168842021-08-17 19:42:21 -070060};
61
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070062// Simple class representing which boot and what monotonic time in that boot.
63// Boots are assumed to be sequential, and the monotonic clock resets on reboot
64// for all the compare operations.
65struct BootTimestamp {
66 // Boot number for this timestamp.
67 size_t boot = 0u;
68 // Monotonic time in that boot.
69 monotonic_clock::time_point time = monotonic_clock::min_time;
70
Austin Schuh66168842021-08-17 19:42:21 -070071 monotonic_clock::duration time_since_epoch() const {
72 return time.time_since_epoch();
73 }
74
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070075 static constexpr BootTimestamp min_time() {
Austin Schuh66168842021-08-17 19:42:21 -070076 return BootTimestamp{.boot = std::numeric_limits<size_t>::min(),
77 .time = monotonic_clock::min_time};
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070078 }
79 static constexpr BootTimestamp max_time() {
80 return BootTimestamp{.boot = std::numeric_limits<size_t>::max(),
81 .time = monotonic_clock::max_time};
82 }
Austin Schuh66168842021-08-17 19:42:21 -070083 static constexpr BootTimestamp epoch() {
84 return BootTimestamp{.boot = 0, .time = monotonic_clock::epoch()};
85 }
Austin Schuh2dc8c7d2021-07-01 17:41:28 -070086
87 // Compare operators. These are implemented such that earlier boots always
88 // compare less than later boots, and the times are only compared in a single
89 // boot.
90 bool operator<(const BootTimestamp &m2) const;
91 bool operator<=(const BootTimestamp &m2) const;
92 bool operator>=(const BootTimestamp &m2) const;
93 bool operator>(const BootTimestamp &m2) const;
94 bool operator==(const BootTimestamp &m2) const;
95 bool operator!=(const BootTimestamp &m2) const;
Austin Schuh66168842021-08-17 19:42:21 -070096
97 BootTimestamp operator+(monotonic_clock::duration d) const {
98 return {boot, time + d};
99 }
Austin Schuhf1dace42022-07-13 22:37:12 -0700100
101 BootTimestamp operator+=(monotonic_clock::duration d) {
102 time += d;
103 return *this;
104 }
Austin Schuh66168842021-08-17 19:42:21 -0700105 BootTimestamp operator-(monotonic_clock::duration d) const {
106 return {boot, time - d};
107 }
108 BootTimestamp operator+(BootDuration d) const {
109 return {boot, time + d.duration};
110 }
Austin Schuh153bc6c2022-07-14 18:17:25 -0700111
112 BootDuration operator-(BootTimestamp t) const {
113 CHECK_EQ(t.boot, boot);
114 return {boot, time - t.time};
115 }
Austin Schuh2dc8c7d2021-07-01 17:41:28 -0700116};
117
Austin Schuh58646e22021-08-23 23:51:46 -0700118// Structure to hold both a boot and queue index. Queue indices reset after
119// reboot, so we need to track them.
120struct BootQueueIndex {
121 // Boot number for this queue index.
122 size_t boot = std::numeric_limits<size_t>::max();
123 // Queue index.
124 uint32_t index = std::numeric_limits<uint32_t>::max();
125
126 // Returns a QueueIndex representing an invalid index. Since
127 // std::numeric_limits<uint32_t>::max() is never used in the QueueIndex code
128 // and is reserved as an Invalid value, this will never collide.
129 static BootQueueIndex Invalid() {
130 return {.boot = std::numeric_limits<size_t>::max(),
131 .index = std::numeric_limits<uint32_t>::max()};
132 }
133
134 bool operator==(const BootQueueIndex &b2) const {
135 return index == b2.index && boot == b2.boot;
136 }
137 bool operator!=(const BootQueueIndex &b2) const {
138 return index != b2.index || boot != b2.boot;
139 }
140 bool operator<(const BootQueueIndex &b2) const {
141 if (boot == b2.boot) {
142 return index < b2.index;
143 }
144 return boot < b2.boot;
145 }
146 bool operator>(const BootQueueIndex &b2) const {
147 if (boot == b2.boot) {
148 return index > b2.index;
149 }
150 return boot > b2.boot;
151 }
152};
153
Austin Schuh2dc8c7d2021-07-01 17:41:28 -0700154std::ostream &operator<<(std::ostream &os,
155 const struct BootTimestamp &timestamp);
Austin Schuh66168842021-08-17 19:42:21 -0700156std::ostream &operator<<(std::ostream &os, const struct BootDuration &duration);
Austin Schuh58646e22021-08-23 23:51:46 -0700157std::ostream &operator<<(std::ostream &os,
158 const struct BootQueueIndex &queue_index);
Austin Schuh2dc8c7d2021-07-01 17:41:28 -0700159
160inline bool BootTimestamp::operator<(const BootTimestamp &m2) const {
161 if (boot != m2.boot) {
162 return boot < m2.boot;
163 }
164
165 return time < m2.time;
166}
167inline bool BootTimestamp::operator<=(const BootTimestamp &m2) const {
168 if (boot != m2.boot) {
169 return boot <= m2.boot;
170 }
171
172 return time <= m2.time;
173}
174inline bool BootTimestamp::operator>=(const BootTimestamp &m2) const {
175 if (boot != m2.boot) {
176 return boot >= m2.boot;
177 }
178
179 return time >= m2.time;
180}
181inline bool BootTimestamp::operator>(const BootTimestamp &m2) const {
182 if (boot != m2.boot) {
183 return boot > m2.boot;
184 }
185
186 return time > m2.time;
187}
188
189inline bool BootTimestamp::operator==(const BootTimestamp &m2) const {
190 return boot == m2.boot && time == m2.time;
191}
192inline bool BootTimestamp::operator!=(const BootTimestamp &m2) const {
193 return boot != m2.boot || time != m2.time;
194}
195
196} // namespace aos::logger
197
198#endif // AOS_EVENTS_LOGGING_BOOT_TIMESTAMP_H_