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/utility.hpp"
12#include "../macros.hpp"
13#include <atomic>
14#include <type_traits>
15#include <bit>
16
17
18
19hi_warning_push();
20// C26490: Don't use reinterpret_cast
21// Need it for allow the use of enum in an atomic operation.
22hi_warning_ignore_msvc(26490);
23
24namespace hi { inline namespace v1 {
25
30enum class global_state_type : uint64_t {
31 log_debug = 0x01,
32 log_info = 0x02,
33 log_statistics = 0x04,
34 log_trace = 0x08,
35 log_audit = 0x10,
36 log_warning = 0x20,
37 log_error = 0x40,
38 log_fatal = 0x80,
39
40 log_mask = log_debug | log_info | log_statistics | log_trace | log_audit | log_warning | log_error | log_fatal,
41
42 log_level_default = log_audit | log_error | log_fatal,
43 log_level_fatal = log_audit | log_fatal,
44 log_level_error = log_trace | log_error | log_level_fatal,
45 log_level_warning = log_warning | log_level_error,
46 log_level_info = log_info | log_statistics | log_level_warning,
47 log_level_debug = log_debug | log_level_info,
48
49 log_is_running = 0x1'00,
50 time_stamp_utc_is_running = 0x2'00,
51
52 system_is_running = 0x1'000000'00,
53 system_is_shutting_down = 0x2'000000'00,
54 system_mask = system_is_running | system_is_shutting_down,
55};
56
57[[nodiscard]] constexpr global_state_type operator|(global_state_type lhs, global_state_type rhs) noexcept
58{
59 return static_cast<global_state_type>(std::to_underlying(lhs) | std::to_underlying(rhs));
60}
61
62[[nodiscard]] constexpr global_state_type operator&(global_state_type lhs, global_state_type rhs) noexcept
63{
64 return static_cast<global_state_type>(std::to_underlying(lhs) & std::to_underlying(rhs));
65}
66
67[[nodiscard]] constexpr global_state_type operator~(global_state_type rhs) noexcept
68{
69 return static_cast<global_state_type>(~std::to_underlying(rhs));
70}
71
72[[nodiscard]] constexpr bool to_bool(global_state_type rhs) noexcept
73{
74 return to_bool(std::to_underlying(rhs));
75}
76
77[[nodiscard]] constexpr bool is_system_running(global_state_type rhs) noexcept
78{
79 return (rhs & global_state_type::system_mask) == global_state_type::system_is_running;
80}
81
82[[nodiscard]] constexpr bool is_system_shutting_down(global_state_type rhs) noexcept
83{
84 return to_bool(rhs & global_state_type::system_is_shutting_down);
85}
86
87}} // namespace hi::v1
88
89template<>
90struct std::atomic<hi::global_state_type> {
94
95 constexpr static bool is_always_lock_free = atomic_type::is_always_lock_free;
96
97 constexpr atomic() noexcept = default;
98 atomic(atomic const&) = delete;
99 atomic(atomic&&) = delete;
100 atomic& operator=(atomic const&) = delete;
101 atomic& operator=(atomic&&) = delete;
102
103 constexpr atomic(value_type desired) noexcept : v(std::to_underlying(desired)) {}
104
105 [[nodiscard]] bool is_lock_free() const noexcept
106 {
107 return v.is_lock_free();
108 }
109
110 void store(value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
111 {
112 return v.store(std::to_underlying(desired), order);
113 }
114
115 [[nodiscard]] value_type load(std::memory_order order = std::memory_order::seq_cst) const noexcept
116 {
117 return static_cast<value_type>(v.load(order));
118 }
119
120 [[nodiscard]] value_type exchange(value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
121 {
122 return static_cast<value_type>(v.exchange(std::to_underlying(desired), order));
123 }
124
125 [[nodiscard]] bool
126 compare_exchange_weak(value_type& expected, value_type desired, std::memory_order success, std::memory_order failure) noexcept
127 {
128 return v.compare_exchange_weak(
129 reinterpret_cast<underlying_type_t<value_type>&>(expected), std::to_underlying(desired), success, failure);
130 }
131
132 [[nodiscard]] bool
133 compare_exchange_weak(value_type& expected, value_type desired, std::memory_order order = std::memory_order::seq_cst) noexcept
134 {
135 return compare_exchange_weak(expected, desired, order, order);
136 }
137
138 [[nodiscard]] bool compare_exchange_strong(
139 value_type& expected,
140 value_type desired,
141 std::memory_order success,
142 std::memory_order failure) noexcept
143 {
144 return v.compare_exchange_weak(
145 reinterpret_cast<underlying_type_t<value_type>&>(expected), std::to_underlying(desired), success, failure);
146 }
147
148 [[nodiscard]] bool compare_exchange_strong(
149 value_type& expected,
150 value_type desired,
151 std::memory_order order = std::memory_order::seq_cst) noexcept
152 {
153 return compare_exchange_strong(expected, desired, order, order);
154 }
155
156 value_type fetch_and(value_type arg, std::memory_order order = std::memory_order::seq_cst) noexcept
157 {
158 return static_cast<value_type>(v.fetch_and(std::to_underlying(arg), order));
159 }
160
161 value_type fetch_or(value_type arg, std::memory_order order = std::memory_order::seq_cst) noexcept
162 {
163 return static_cast<value_type>(v.fetch_or(std::to_underlying(arg), order));
164 }
165
166 operator value_type() const noexcept
167 {
168 return load();
169 }
170
171 value_type operator=(value_type desired) noexcept
172 {
173 store(desired);
174 return desired;
175 }
176
177 value_type operator|=(value_type arg) noexcept
178 {
179 return fetch_or(arg) | arg;
180 }
181
182 value_type operator&=(value_type arg) noexcept
183 {
184 return fetch_and(arg) & arg;
185 }
186};
187
188namespace hi { inline namespace v1 {
189
201inline std::atomic<global_state_type> global_state = global_state_type::log_level_default;
202
210{
211 return is_system_running(global_state.load(std::memory_order::relaxed));
212}
213
221{
222 return is_system_shutting_down(global_state.load(std::memory_order::relaxed));
223}
224
231{
232 // Only the log_* bits should be set.
233 hi_assert(not to_bool(log_level & ~global_state_type::log_mask));
234
235 // First enable bits, then disable bits.
238}
239
247inline bool global_state_disable(global_state_type subsystem, std::memory_order order = std::memory_order::seq_cst) noexcept
248{
249 hi_assert(std::popcount(std::to_underlying(subsystem)) == 1);
250 return to_bool(global_state.fetch_and(~subsystem, order) & subsystem);
251}
252
260inline bool global_state_enable(global_state_type subsystem, std::memory_order order = std::memory_order::seq_cst) noexcept
261{
262 hi_assert(std::popcount(std::to_underlying(subsystem)) == 1);
263 return to_bool(global_state.fetch_or(subsystem, order) & subsystem);
264}
265
266}} // namespace hi::v1
267
268hi_warning_pop();
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:260
bool is_system_running() noexcept
Check if the HikoGUI system is running.
Definition global_state.hpp:209
std::atomic< global_state_type > global_state
The global state of the hikogui framework.
Definition global_state.hpp:201
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:247
global_state_type
The flag-type used for global state.
Definition global_state.hpp:30
bool is_system_shutting_down() noexcept
Check if the HikoGUI system is being shut down.
Definition global_state.hpp:220
void set_log_level(global_state_type log_level) noexcept
Set the logging level.
Definition global_state.hpp:230
DOXYGEN BUG.
Definition algorithm.hpp:16
geometry/margins.hpp
Definition lookahead_iterator.hpp:5
constexpr Out narrow_cast(In const &rhs) noexcept
Cast numeric values without loss of precision.
Definition cast.hpp:377
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)