HikoGUI
A low latency retained GUI
Loading...
Searching...
No Matches
global_state.hpp
Go to the documentation of this file.
1// Copyright Take Vos 2021-2022.
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
9#pragma once
10
11#include "../utility/module.hpp"
12#include <atomic>
13#include <type_traits>
14#include <bit>
15
16hi_warning_push();
17// C26490: Don't use reinterpret_cast
18// Need it for allow the use of enum in an atomic operation.
19hi_warning_ignore_msvc(26490);
20
21namespace hi { inline namespace v1 {
22
27enum class global_state_type : uint64_t {
28 log_debug = 0x01,
29 log_info = 0x02,
30 log_statistics = 0x04,
31 log_trace = 0x08,
32 log_audit = 0x10,
33 log_warning = 0x20,
34 log_error = 0x40,
35 log_fatal = 0x80,
36
37 log_mask = log_debug | log_info | log_statistics | log_trace | log_audit | log_warning | log_error | log_fatal,
38
39 log_level_default = log_audit | log_error | log_fatal,
40 log_level_fatal = log_audit | log_fatal,
41 log_level_error = log_trace | log_error | log_level_fatal,
42 log_level_warning = log_warning | log_level_error,
43 log_level_info = log_info | log_statistics | log_level_warning,
44 log_level_debug = log_debug | log_level_info,
45
46 log_is_running = 0x1'00,
47 time_stamp_utc_is_running = 0x2'00,
48
49 system_is_running = 0x1'000000'00,
50 system_is_shutting_down = 0x2'000000'00,
51 system_mask = system_is_running | system_is_shutting_down,
52};
53
54[[nodiscard]] constexpr global_state_type operator|(global_state_type lhs, global_state_type rhs) noexcept
55{
56 return static_cast<global_state_type>(to_underlying(lhs) | to_underlying(rhs));
57}
58
59[[nodiscard]] constexpr global_state_type operator&(global_state_type lhs, global_state_type rhs) noexcept
60{
61 return static_cast<global_state_type>(to_underlying(lhs) & to_underlying(rhs));
62}
63
64[[nodiscard]] constexpr global_state_type operator~(global_state_type rhs) noexcept
65{
66 return static_cast<global_state_type>(~to_underlying(rhs));
67}
68
69[[nodiscard]] constexpr bool to_bool(global_state_type rhs) noexcept
70{
71 return to_bool(to_underlying(rhs));
72}
73
74[[nodiscard]] constexpr bool is_system_running(global_state_type rhs) noexcept
75{
76 return (rhs & global_state_type::system_mask) == global_state_type::system_is_running;
77}
78
79[[nodiscard]] constexpr bool is_system_shutting_down(global_state_type rhs) noexcept
80{
81 return to_bool(rhs & global_state_type::system_is_shutting_down);
82}
83
84}} // namespace hi::v1
85
86template<>
87struct std::atomic<hi::global_state_type> {
91
92 static constexpr bool is_always_lock_free = atomic_type::is_always_lock_free;
93
94 constexpr atomic() noexcept = default;
95 atomic(atomic const&) = delete;
96 atomic(atomic&&) = delete;
97 atomic& operator=(atomic const&) = delete;
98 atomic& operator=(atomic&&) = delete;
99
100 constexpr atomic(value_type desired) noexcept : v(to_underlying(desired)) {}
101
102 [[nodiscard]] bool is_lock_free() const noexcept
103 {
104 return v.is_lock_free();
105 }
106
107 void store(value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
108 {
109 return v.store(hi::to_underlying(desired), order);
110 }
111
112 [[nodiscard]] value_type load(std::memory_order order = std::memory_order::seq_cst) const noexcept
113 {
114 return static_cast<value_type>(v.load(order));
115 }
116
117 [[nodiscard]] value_type exchange(value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
118 {
119 return static_cast<value_type>(v.exchange(hi::to_underlying(desired), order));
120 }
121
122 [[nodiscard]] bool
123 compare_exchange_weak(value_type& expected, value_type desired, std::memory_order success, std::memory_order failure) noexcept
124 {
125 return v.compare_exchange_weak(
126 reinterpret_cast<underlying_type_t<value_type>&>(expected), hi::to_underlying(desired), success, failure);
127 }
128
129 [[nodiscard]] bool
130 compare_exchange_weak(value_type& expected, value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
131 {
132 return compare_exchange_weak(expected, desired, order, order);
133 }
134
135 [[nodiscard]] bool compare_exchange_strong(
136 value_type& expected,
137 value_type desired,
138 std::memory_order success,
139 std::memory_order failure) noexcept
140 {
141 return v.compare_exchange_weak(
142 reinterpret_cast<underlying_type_t<value_type>&>(expected), hi::to_underlying(desired), success, failure);
143 }
144
145 [[nodiscard]] bool compare_exchange_strong(
146 value_type& expected,
147 value_type desired,
148 std::memory_order order = std::memory_order::seq_cst) noexcept
149 {
150 return compare_exchange_strong(expected, desired, order, order);
151 }
152
153 value_type fetch_and(value_type arg, std::memory_order order = std::memory_order::seq_cst) noexcept
154 {
155 return static_cast<value_type>(v.fetch_and(hi::to_underlying(arg), order));
156 }
157
158 value_type fetch_or(value_type arg, std::memory_order order = std::memory_order::seq_cst) noexcept
159 {
160 return static_cast<value_type>(v.fetch_or(hi::to_underlying(arg), order));
161 }
162
163 operator value_type() const noexcept
164 {
165 return load();
166 }
167
168 value_type operator=(value_type desired) noexcept
169 {
170 store(desired);
171 return desired;
172 }
173
174 value_type operator|=(value_type arg) noexcept
175 {
176 return fetch_or(arg) | arg;
177 }
178
179 value_type operator&=(value_type arg) noexcept
180 {
181 return fetch_and(arg) & arg;
182 }
183};
184
185namespace hi { inline namespace v1 {
186
198inline std::atomic<global_state_type> global_state = global_state_type::log_level_default;
199
206[[nodiscard]] inline bool is_system_running() noexcept
207{
208 return is_system_running(global_state.load(std::memory_order::relaxed));
209}
210
217[[nodiscard]] inline bool is_system_shutting_down() noexcept
218{
219 return is_system_shutting_down(global_state.load(std::memory_order::relaxed));
220}
221
227inline void set_log_level(global_state_type log_level) noexcept
228{
229 // Only the log_* bits should be set.
230 hi_assert(not to_bool(log_level & ~global_state_type::log_mask));
231
232 // First enable bits, then disable bits.
233 global_state |= log_level;
234 global_state &= (~global_state_type::log_mask | log_level);
235}
236
244inline bool global_state_disable(global_state_type subsystem, std::memory_order order = std::memory_order::seq_cst) noexcept
245{
246 hi_assert(std::popcount(to_underlying(subsystem)) == 1);
247 return to_bool(global_state.fetch_and(~subsystem, order) & subsystem);
248}
249
257inline bool global_state_enable(global_state_type subsystem, std::memory_order order = std::memory_order::seq_cst) noexcept
258{
259 hi_assert(std::popcount(to_underlying(subsystem)) == 1);
260 return to_bool(global_state.fetch_or(subsystem, order) & subsystem);
261}
262
263}} // namespace hi::v1
264
265hi_warning_pop();
#define hi_assert(expression,...)
Assert if expression is true.
Definition assert.hpp:184
bool global_state_enable(global_state_type subsystem, std::memory_order order=std::memory_order::seq_cst) noexcept
Enable a subsystem.
Definition global_state.hpp:257
bool is_system_running() noexcept
Check if the HikoGUI system is running.
Definition global_state.hpp:206
std::atomic< global_state_type > global_state
The global state of the hikogui framework.
Definition global_state.hpp:198
bool global_state_disable(global_state_type subsystem, std::memory_order order=std::memory_order::seq_cst) noexcept
Disable a subsystem.
Definition global_state.hpp:244
global_state_type
The flag-type used for global state.
Definition global_state.hpp:27
bool is_system_shutting_down() noexcept
Check if the HikoGUI system is being shut down.
Definition global_state.hpp:217
void set_log_level(global_state_type log_level) noexcept
Set the logging level.
Definition global_state.hpp:227
DOXYGEN BUG.
Definition algorithm.hpp:13
geometry/margins.hpp
Definition cache.hpp:11
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)