8#include "unfair_recursive_mutex.hpp"
10#include "global_state.hpp"
18namespace hi::inline
v1 {
23inline std::vector<void (*)()> subsystem_deinit_list;
29inline unfair_recursive_mutex subsystem_mutex;
32hi_no_inline
typename T::value_type start_subsystem(
34 typename T::value_type off_value,
35 typename T::value_type (*init_function)(),
36 void (*deinit_function)())
requires(is_atomic_v<T>)
38 hi_axiom(init_function !=
nullptr);
39 hi_axiom(deinit_function !=
nullptr);
40 hilet lock = std::scoped_lock(subsystem_mutex);
42 hilet old_value = check_variable.load(std::memory_order::acquire);
43 if (old_value != off_value) {
48 if (not is_system_running()) {
54 auto new_value = init_function();
56 if (new_value != off_value) {
57 subsystem_deinit_list.emplace_back(deinit_function);
58 check_variable.store(new_value, std::memory_order::release);
64hi_no_inline
inline bool start_subsystem(global_state_type state_bit,
bool (*init_function)(),
void (*deinit_function)())
66 hi_axiom(std::popcount(to_underlying(state_bit)) == 1);
67 hi_axiom(init_function !=
nullptr);
68 hi_axiom(deinit_function !=
nullptr);
70 hilet lock = std::scoped_lock(subsystem_mutex);
73 if (not is_system_running(old_state)) {
78 }
else if (to_bool(old_state & state_bit)) {
83 if (init_function()) {
84 subsystem_deinit_list.emplace_back(deinit_function);
108typename T::value_type start_subsystem(
110 typename T::value_type off_value,
111 typename T::value_type (*init_function)(),
112 void (*deinit_function)())
requires(is_atomic_v<T>)
117 hilet old_value = check_variable.load(std::memory_order::relaxed);
118 if (old_value == off_value) {
119 return detail::start_subsystem(check_variable, off_value, init_function, deinit_function);
121 [[likely]]
return old_value;
137inline bool start_subsystem(global_state_type state_bit,
bool (*init_function)(),
void (*deinit_function)())
142 if (not to_bool(
global_state.load(std::memory_order::relaxed) & state_bit)) {
143 return detail::start_subsystem(state_bit, init_function, deinit_function);
145 [[likely]]
return true;
168 typename T::value_type off_value,
169 typename T::value_type (*init_function)(),
170 void (*deinit_function)())
172 auto old_value = check_variable.load(std::memory_order::acquire);
173 if (old_value == off_value) {
174 auto tmp = detail::start_subsystem(check_variable, off_value, init_function, deinit_function);
175 hi_assert(tmp != off_value);
178 [[likely]]
return old_value;
191 hi_axiom(deinit_function !=
nullptr);
193 hilet lock = std::scoped_lock(detail::subsystem_mutex);
195 std::erase(detail::subsystem_deinit_list, deinit_function);
196 return deinit_function();
215 detail::subsystem_mutex.lock();
216 global_state |= global_state_type::system_is_shutting_down;
218 while (!detail::subsystem_deinit_list.empty()) {
219 auto deinit =
std::move(detail::subsystem_deinit_list.back());
220 hi_axiom(deinit !=
nullptr);
221 detail::subsystem_deinit_list.pop_back();
223 detail::subsystem_mutex.unlock();
225 detail::subsystem_mutex.lock();
227 detail::subsystem_mutex.unlock();
#define hilet
Invariant should be the default for variables.
Definition utility.hpp:23
DOXYGEN BUG.
Definition algorithm.hpp:15
void start_system() noexcept
Start the system.
Definition subsystem.hpp:202
void shutdown_system() noexcept
Shutdown the system.
Definition subsystem.hpp:213
std::atomic< global_state_type > global_state
The global state of the hikogui framework.
Definition global_state.hpp:187
T::value_type start_subsystem_or_terminate(T &check_variable, typename T::value_type off_value, typename T::value_type(*init_function)(), void(*deinit_function)())
Start a sub-system.
Definition subsystem.hpp:166
void stop_subsystem(void(*deinit_function)())
Stop a sub-system.
Definition subsystem.hpp:189
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:227