Skip to content

Commit 91af84b

Browse files
committedJul 22, 2023
feat: strict typing for thread ids, time and other helper functions
1 parent 0159f77 commit 91af84b

File tree

1 file changed

+246
-0
lines changed

1 file changed

+246
-0
lines changed
 

‎include/zephyr/strong_types.hpp

+246
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
#ifndef ZEPHYR_STRONG_TYPES_HPP_
2+
#define ZEPHYR_STRONG_TYPES_HPP_
3+
4+
#include <chrono>
5+
#include <concepts>
6+
#include <cstdint>
7+
#include <limits>
8+
#include <ostream>
9+
10+
namespace ze {
11+
12+
/**
13+
* A struct for providing strict typing of thread ids'.
14+
*/
15+
struct thread_t {
16+
17+
/**
18+
* @brief This value signifies either no thread or any thread is allowed.
19+
*/
20+
static constexpr auto ANY_THREAD = std::numeric_limits<std::uint16_t>::max() - 1;
21+
22+
/**
23+
* @brief The logical thread ID
24+
*/
25+
std::uint16_t m_thread = ANY_THREAD;
26+
27+
/**
28+
* @brief Gets a thread_t object with its value initialised to ANY_THREAD
29+
*
30+
* @return constexpr thread_t
31+
*/
32+
static constexpr thread_t any_thread() {
33+
return thread_t{ANY_THREAD};
34+
}
35+
36+
/**
37+
* @brief Equality operator is default.
38+
*
39+
* @param _first The lhs
40+
* @param _second The rhs
41+
* @return true If equal
42+
* @return false If not equal
43+
*/
44+
friend constexpr bool operator==(const thread_t _first, const thread_t _second) = default;
45+
46+
/**
47+
* @brief Inequality operator is default.
48+
*
49+
* @param _first The lhs.
50+
* @param _second The rhs.
51+
* @return true If not equal
52+
* @return false If equal
53+
*/
54+
friend constexpr bool operator!=(const thread_t _first, const thread_t _second) = default;
55+
56+
/**
57+
* @brief 3-way operator is default for a std::strong_ordering.
58+
*
59+
* @param _first The lhs.
60+
* @param _second The rhs.
61+
*/
62+
friend constexpr auto operator<=>(const thread_t _first, const thread_t _second) {
63+
return _first.m_thread <=> _second.m_thread;
64+
}
65+
66+
/**
67+
* @brief 3-way operator with a std::integral for a std::strong_ordering.
68+
*
69+
* @param _first The lhs.
70+
* @param _second The rhs.
71+
*/
72+
template <std::integral T>
73+
friend constexpr auto operator<=>(const thread_t _first, const T _number) {
74+
return _first.m_thread <=> _number;
75+
}
76+
77+
/**
78+
* @brief Equality operator with a std::integral.
79+
*
80+
* @param _first The lhs
81+
* @param _second The rhs
82+
* @return true If equal
83+
* @return false If not equal
84+
*/
85+
template <std::integral T>
86+
friend constexpr bool operator==(const thread_t _first, const T _second) {
87+
return _first.m_thread == _second;
88+
}
89+
90+
/**
91+
* @brief Inequality operator with a std::integral.
92+
*
93+
* @param _first The lhs
94+
* @param _second The rhs
95+
* @return true If equal
96+
* @return false If not equal
97+
*/
98+
template <std::integral T>
99+
friend constexpr bool operator!=(const thread_t& _first, const T _second) {
100+
return _first.m_thread != _second;
101+
}
102+
};
103+
104+
/**
105+
* @brief Namespace for thread_t based operations
106+
*/
107+
namespace thread {
108+
109+
/**
110+
* @brief Construct a thread_t based of an id.
111+
*
112+
* @param _thread The thread id.
113+
* @return constexpr auto thread_t{_thread}
114+
*/
115+
constexpr auto in(std::uint16_t _thread) noexcept {
116+
return thread_t{_thread};
117+
}
118+
119+
/**
120+
* @brief Get a thread_t for any thread.
121+
*
122+
* @return constexpr auto thread_t{}
123+
*/
124+
constexpr auto any() noexcept {
125+
return thread_t{};
126+
}
127+
} // namespace thread
128+
129+
/**
130+
* @brief Print the value of a thread to a stream.
131+
*
132+
* @param _os The out stream.
133+
* @param _thread The thread to print.
134+
* @return std::ostream& _os
135+
*/
136+
inline std::ostream& operator<<(std::ostream& _os, const thread_t _thread) {
137+
_os << "thread[" << _thread.m_thread << "]";
138+
return _os;
139+
}
140+
141+
/**
142+
* @brief A struct for providing strict typing for timing.
143+
*/
144+
struct order_t {
145+
146+
/**
147+
* @brief The amount of time in nanoseconds.
148+
*/
149+
std::uint64_t m_order = 0;
150+
151+
/**
152+
* @brief 3-way operator for a std::strong_ordering
153+
*/
154+
constexpr auto operator<=>(const order_t& _other) const {
155+
return m_order <=> _other.m_order;
156+
}
157+
158+
/**
159+
* @brief 3-way operator with a std::integral for a std::strong_ordering
160+
*/
161+
template <std::integral Integral>
162+
constexpr auto operator<=>(const Integral _number) const {
163+
return m_order <=> _number;
164+
}
165+
166+
/**
167+
* @brief Add two order_t's together.
168+
*
169+
* @param _lhs The lhs.
170+
* @param _rhs The rhs.
171+
* @return constexpr auto order_t{_lhs.order_ + _rhs.order_}
172+
*/
173+
friend constexpr auto operator+(order_t lhs, order_t rhs) noexcept {
174+
return order_t{lhs.m_order + rhs.m_order};
175+
}
176+
177+
/**
178+
* @brief subtract two order_t's together.
179+
*
180+
* @param _lhs The lhs.
181+
* @param _rhs The rhs.
182+
* @return constexpr auto order_t{_lhs.order_ - _rhs.order_}
183+
*/
184+
friend constexpr auto operator-(order_t lhs, order_t rhs) noexcept{
185+
return order_t{lhs.m_order - rhs.m_order};
186+
}
187+
};
188+
189+
/**
190+
* @brief Namespace for order_t based helper functions.
191+
*/
192+
namespace order {
193+
194+
/**
195+
* @brief Get an order_t for _number seconds.
196+
*
197+
* @param _number The number of seconds.
198+
* @return constexpr order_t order_t{_number * 1000000000}
199+
*/
200+
inline constexpr order_t seconds(std::uint64_t _number) noexcept {
201+
return order_t{_number * 1000000000};
202+
}
203+
204+
/**
205+
* @brief Get an order_t for _number seconds.
206+
*
207+
* @param _number The number of seconds.
208+
* @return constexpr order_t order_t{_number * 1000000000}
209+
*/
210+
inline constexpr order_t in_seconds(std::uint64_t _number) noexcept {
211+
return seconds(_number);
212+
}
213+
214+
/**
215+
* @brief Get an order_t for _number milliseconds.
216+
*
217+
* @param _number The number of milliseconds.
218+
* @return constexpr order_t order_t{_number * 1000000}
219+
*/
220+
inline constexpr order_t milli(std::uint64_t _number) noexcept {
221+
return order_t{_number * 1000000};
222+
}
223+
224+
/**
225+
* @brief Get an order_t for _number milliseconds.
226+
*
227+
* @param _number The number of milliseconds.
228+
* @return constexpr order_t order_t{_number * 1000000}
229+
*/
230+
inline constexpr order_t in_milli(std::uint64_t _number) noexcept {
231+
return milli(_number);
232+
}
233+
234+
/**
235+
* @brief Get an order_t that represents now.
236+
*
237+
* @return constexpr order_t order_t{};
238+
*/
239+
inline constexpr order_t now() noexcept {
240+
return order_t{};
241+
}
242+
243+
} // namespace order
244+
} // namespace ze
245+
246+
#endif // ZEPHYR_STRONG_TYPES_HPP_

0 commit comments

Comments
 (0)