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);
72 hilet old_state = global_state.load(std::memory_order::acquire);
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);
85 global_state_enable(state_bit, std::memory_order::release);
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;
166requires(is_atomic_v<T>)
typename T::value_type start_subsystem_or_terminate(
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;
189inline void stop_subsystem(
void (*deinit_function)())
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();
202inline void start_system() noexcept
204 global_state |= global_state_type::system_is_running;
213inline void shutdown_system() noexcept
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 required.hpp:23