HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
global_state.hpp
1// Copyright Take Vos 2021.
2// Distributed under the Boost Software License, Version 1.0.
3// (See accompanying file LICENSE_1_0.txt or copy at https://www.boost.org/LICENSE_1_0.txt)
4
5#pragma once
6
7#include "cast.hpp"
8#include <atomic>
9#include <type_traits>
10#include <bit>
11
12namespace tt {
13
14enum class global_state_type : uint64_t {
15 log_debug = 0x01,
16 log_info = 0x02,
17 log_statistics = 0x04,
18 log_trace = 0x08,
19 log_audit = 0x10,
20 log_warning = 0x20,
21 log_error = 0x40,
22 log_fatal = 0x80,
23
24 log_mask = log_debug | log_info | log_statistics | log_trace | log_audit | log_warning | log_error | log_fatal,
25
26 log_level_default = log_audit | log_error | log_fatal,
27 log_level_fatal = log_audit | log_fatal,
28 log_level_error = log_trace | log_error | log_level_fatal,
29 log_level_warning = log_warning | log_level_error,
30 log_level_info = log_info | log_statistics | log_level_warning,
31 log_level_debug = log_debug | log_level_info,
32
33 log_is_running = 0x1'00,
34 time_stamp_utc_is_running = 0x2'00,
35
36 system_is_running = 0x1'000000'00,
37 system_is_shutting_down = 0x2'000000'00,
38 system_mask = system_is_running | system_is_shutting_down,
39};
40
41[[nodiscard]] constexpr global_state_type operator|(global_state_type lhs, global_state_type rhs) noexcept
42{
43 return static_cast<global_state_type>(to_underlying(lhs) | to_underlying(rhs));
44}
45
46[[nodiscard]] constexpr global_state_type operator&(global_state_type lhs, global_state_type rhs) noexcept
47{
48 return static_cast<global_state_type>(to_underlying(lhs) & to_underlying(rhs));
49}
50
51[[nodiscard]] constexpr global_state_type operator~(global_state_type rhs) noexcept
52{
53 return static_cast<global_state_type>(~to_underlying(rhs));
54}
55
56[[nodiscard]] constexpr bool to_bool(global_state_type rhs) noexcept
57{
58 return static_cast<bool>(to_underlying(rhs));
59}
60
61[[nodiscard]] constexpr bool is_system_running(global_state_type rhs) noexcept
62{
63 return (rhs & global_state_type::system_mask) == global_state_type::system_is_running;
64}
65
66[[nodiscard]] constexpr bool is_system_shutting_down(global_state_type rhs) noexcept
67{
68 return to_bool(rhs & global_state_type::system_is_shutting_down);
69}
70
71} // namespace tt
72
73namespace std {
74
75template<>
76struct atomic<tt::global_state_type> {
77 using value_type = tt::global_state_type;
80
81 static constexpr bool is_always_lock_free = atomic_type::is_always_lock_free;
82
83 constexpr atomic() noexcept = default;
84 constexpr atomic(value_type desired) noexcept : v(to_underlying(desired)) {}
85 constexpr atomic(atomic const &) = delete;
86
87 atomic &operator=(const atomic &) = delete;
88
89 [[nodiscard]] bool is_lock_free() const noexcept
90 {
91 return v.is_lock_free();
92 }
93
94 void store(value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
95 {
96 return v.store(tt::to_underlying(desired), order);
97 }
98
99 [[nodiscard]] value_type load(std::memory_order order = std::memory_order::seq_cst) const noexcept
100 {
101 return static_cast<value_type>(v.load(order));
102 }
103
104 [[nodiscard]] value_type exchange(value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
105 {
106 return static_cast<value_type>(v.exchange(tt::to_underlying(desired), order));
107 }
108
109 [[nodiscard]] bool
110 compare_exchange_weak(value_type &expected, value_type desired, std::memory_order success, std::memory_order failure) noexcept
111 {
112 return v.compare_exchange_weak(
113 reinterpret_cast<underlying_type_t<value_type> &>(expected), tt::to_underlying(desired), success, failure);
114 }
115
116 [[nodiscard]] bool
117 compare_exchange_weak(value_type &expected, value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
118 {
119 return compare_exchange_weak(expected, desired, order, order);
120 }
121
122 [[nodiscard]] bool compare_exchange_strong(
123 value_type &expected,
124 value_type desired,
125 std::memory_order success,
126 std::memory_order failure) noexcept
127 {
128 return v.compare_exchange_weak(
129 reinterpret_cast<underlying_type_t<value_type> &>(expected), tt::to_underlying(desired), success, failure);
130 }
131
132 [[nodiscard]] bool compare_exchange_strong(
133 value_type &expected,
134 value_type desired,
135 std::memory_order order = std::memory_order::seq_cst) noexcept
136 {
137 return compare_exchange_strong(expected, desired, order, order);
138 }
139
140 value_type fetch_and(value_type arg, std::memory_order order = std::memory_order::seq_cst) noexcept
141 {
142 return static_cast<value_type>(v.fetch_and(tt::to_underlying(arg), order));
143 }
144
145 value_type fetch_or(value_type arg, std::memory_order order = std::memory_order::seq_cst) noexcept
146 {
147 return static_cast<value_type>(v.fetch_or(tt::to_underlying(arg), order));
148 }
149
150 operator value_type() const noexcept
151 {
152 return load();
153 }
154
155 value_type operator=(value_type desired) noexcept
156 {
157 store(desired);
158 return desired;
159 }
160
161 value_type operator|=(value_type arg) noexcept
162 {
163 return fetch_or(arg) | arg;
164 }
165
166 value_type operator&=(value_type arg) noexcept
167 {
168 return fetch_and(arg) & arg;
169 }
170};
171
172} // namespace std
173
174namespace tt {
175
185inline std::atomic<global_state_type> global_state = global_state_type::log_level_default;
186
187[[nodiscard]] inline bool is_system_running() noexcept
188{
189 return is_system_running(global_state.load(std::memory_order::relaxed));
190}
191
192[[nodiscard]] inline bool is_system_shutting_down() noexcept
193{
194 return is_system_shutting_down(global_state.load(std::memory_order::relaxed));
195}
196
197[[nodiscard]] inline void set_log_level(global_state_type log_level) noexcept
198{
199 // Only the log_* bits should be set.
200 tt_axiom(not to_bool(log_level & ~global_state_type::log_mask));
201
202 // First enable bits, then disable bits.
203 global_state |= log_level;
204 global_state &= (~global_state_type::log_mask | log_level);
205}
206
212inline bool global_state_disable(global_state_type subsystem, std::memory_order order = std::memory_order::seq_cst) noexcept
213{
214 tt_axiom(std::popcount(to_underlying(subsystem)) == 1);
215 return to_bool(global_state.fetch_and(~subsystem, order) & subsystem);
216}
217
223inline bool global_state_enable(global_state_type subsystem, std::memory_order order = std::memory_order::seq_cst) noexcept
224{
225 tt_axiom(std::popcount(to_underlying(subsystem)) == 1);
226 return to_bool(global_state.fetch_or(subsystem, order) & subsystem);
227}
228
229} // namespace tt
constexpr alignment operator|(vertical_alignment lhs, horizontal_alignment rhs) noexcept
Combine vertical and horizontal alignment.
Definition alignment.hpp:91
STL namespace.
T compare_exchange_weak(T... args)
T exchange(T... args)
T fetch_and(T... args)
T fetch_or(T... args)
T is_lock_free(T... args)
T load(T... args)
T operator=(T... args)
T operator|=(T... args)
T store(T... args)