ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
lifecycle.c
Go to the documentation of this file.
1
12#include <ascii-chat/log/log.h>
13#include <ascii-chat/atomic.h>
14
15static _Thread_local bool g_lifecycle_log_in_progress = false;
16
17#define lifecycle_log_dev(...) \
18 do { \
19 if (!g_lifecycle_log_in_progress) { \
20 g_lifecycle_log_in_progress = true; \
21 log_dev(__VA_ARGS__); \
22 g_lifecycle_log_in_progress = false; \
23 } \
24 } while (0)
25
26bool lifecycle_init(lifecycle_t *lc, const char *name) {
27 if (lc == NULL) {
28 lifecycle_log_dev("[lifecycle] init: NULL lifecycle pointer");
29 return false;
30 }
32 if (!atomic_cas_u64(&lc->state, &expected, LIFECYCLE_INITIALIZED)) {
33 lifecycle_log_dev("[lifecycle] init: %s already initialized (current state: %llu)", name ? name : "<unnamed>",
34 expected);
35 return false; // Already initialized or in INITIALIZING/DEAD state
36 }
37
38 /* Winner: initialize sync primitive if configured */
39 if (lc->sync_type == LIFECYCLE_SYNC_MUTEX && lc->sync.mutex != NULL) {
40 lifecycle_log_dev("[lifecycle] init: %s initializing mutex", name ? name : "<unnamed>");
41 mutex_init(lc->sync.mutex, name);
42 } else if (lc->sync_type == LIFECYCLE_SYNC_RWLOCK && lc->sync.rwlock != NULL) {
43 lifecycle_log_dev("[lifecycle] init: %s initializing rwlock", name ? name : "<unnamed>");
44 rwlock_init(lc->sync.rwlock, name);
45 } else {
46 lifecycle_log_dev("[lifecycle] init: %s initialized (no sync primitive)", name ? name : "<unnamed>");
47 }
48
49 return true;
50}
51
53 if (lc == NULL) {
54 lifecycle_log_dev("[lifecycle] init_once: NULL lifecycle pointer");
55 return false;
56 }
57
59 if (!atomic_cas_u64(&lc->state, &expected, LIFECYCLE_INITIALIZING)) {
60 // If already initialized, just return false (no work needed)
61 if (expected == LIFECYCLE_INITIALIZED) {
62 lifecycle_log_dev("[lifecycle] init_once: already initialized");
63 return false;
64 }
65
66 // If dead, never allow re-init
67 if (expected == LIFECYCLE_DEAD) {
68 lifecycle_log_dev("[lifecycle] init_once: module is dead, no re-init allowed");
69 return false;
70 }
71
72 // If initializing, don't spin (caller may be retrying or it may complete asynchronously)
73 // Just return false to indicate this thread doesn't need to do init work
74 if (expected == LIFECYCLE_INITIALIZING) {
75 lifecycle_log_dev("[lifecycle] init_once: already initializing, skipping (will resolve asynchronously)");
76 return false;
77 }
78
79 // Unexpected state
80 lifecycle_log_dev("[lifecycle] init_once: unexpected state: %d", expected);
81 return false;
82 }
83
84 // Winner: state is now LIFECYCLE_INITIALIZING
85 // Caller must call lifecycle_init_commit() or lifecycle_init_abort()
86 lifecycle_log_dev("[lifecycle] init_once: won CAS, transitioned to INITIALIZING");
87 return true;
88}
89
91 if (lc == NULL) {
92 lifecycle_log_dev("[lifecycle] init_commit: NULL lifecycle pointer");
93 return;
94 }
95 lifecycle_log_dev("[lifecycle] init_commit: transitioning INITIALIZING → INITIALIZED");
97}
98
100 if (lc == NULL) {
101 lifecycle_log_dev("[lifecycle] init_abort: NULL lifecycle pointer");
102 return;
103 }
104 lifecycle_log_dev("[lifecycle] init_abort: transitioning INITIALIZING → UNINITIALIZED (retry allowed)");
106}
107
109 if (lc == NULL) {
110 lifecycle_log_dev("[lifecycle] shutdown: NULL lifecycle pointer");
111 return false;
112 }
114 if (!atomic_cas_u64(&lc->state, &expected, LIFECYCLE_UNINITIALIZED)) {
115 lifecycle_log_dev("[lifecycle] shutdown: not in INITIALIZED state (current: %d)", expected);
116 return false; // Not initialized or in unexpected state
117 }
118
119 /* Winner: destroy sync primitive if configured */
120 if (lc->sync_type == LIFECYCLE_SYNC_MUTEX && lc->sync.mutex != NULL) {
121 lifecycle_log_dev("[lifecycle] shutdown: destroying mutex");
123 } else if (lc->sync_type == LIFECYCLE_SYNC_RWLOCK && lc->sync.rwlock != NULL) {
124 lifecycle_log_dev("[lifecycle] shutdown: destroying rwlock");
126 } else {
127 lifecycle_log_dev("[lifecycle] shutdown: completed (no sync primitive)");
128 }
129
130 return true;
131}
132
134 if (lc == NULL) {
135 log_dev("[lifecycle] shutdown_forever: NULL lifecycle pointer");
136 return false;
137 }
138
139 uint64_t current;
140 do {
141 current = atomic_load_u64(&lc->state);
142 if (current == LIFECYCLE_DEAD) {
143 log_dev("[lifecycle] shutdown_forever: already DEAD");
144 return false;
145 }
146 if (current == LIFECYCLE_INITIALIZING) {
147 log_dev("[lifecycle] shutdown_forever: spinning on INITIALIZING");
148 }
149 } while (current == LIFECYCLE_INITIALIZING || !atomic_cas_u64(&lc->state, &current, LIFECYCLE_DEAD));
150
151 log_dev("[lifecycle] shutdown_forever: transitioned to DEAD (was in state: %d)", current);
152 return current == LIFECYCLE_INITIALIZED;
153}
154
156 if (lc == NULL)
157 return false;
159}
160
162 if (lc == NULL)
163 return false;
164 return atomic_load_u64(&lc->state) == LIFECYCLE_DEAD;
165}
166
168 if (lc == NULL) {
169 log_dev("[lifecycle] reset: NULL lifecycle pointer");
170 return false;
171 }
172
174 if (!atomic_cas_u64(&lc->state, &expected, LIFECYCLE_UNINITIALIZED)) {
175 log_dev("[lifecycle] reset: not in INITIALIZED state (current: %d)", expected);
176 return false; // Not in INITIALIZED state
177 }
178
179 /* Winner: destroy sync primitive if configured (reset keeps same primitive) */
180 if (lc->sync_type == LIFECYCLE_SYNC_MUTEX && lc->sync.mutex != NULL) {
181 log_dev("[lifecycle] reset: destroying and resetting mutex");
183 } else if (lc->sync_type == LIFECYCLE_SYNC_RWLOCK && lc->sync.rwlock != NULL) {
184 log_dev("[lifecycle] reset: destroying and resetting rwlock");
186 } else {
187 log_dev("[lifecycle] reset: completed (no sync primitive, allows reinit)");
188 }
189
190 return true;
191}
192
194 if (lc == NULL) {
195 log_dev("[lifecycle] destroy_once: NULL lifecycle pointer");
196 return false;
197 }
198
200 if (!atomic_cas_u64(&lc->state, &expected, LIFECYCLE_DESTROYING)) {
201 // If not initialized, nothing to destroy
202 if (expected == LIFECYCLE_UNINITIALIZED) {
203 log_dev("[lifecycle] destroy_once: already uninitialized, nothing to destroy");
204 return false;
205 }
206
207 // If dead, never allow destruction (already permanently shut down)
208 if (expected == LIFECYCLE_DEAD) {
209 log_dev("[lifecycle] destroy_once: module is dead, no destruction allowed");
210 return false;
211 }
212
213 // If already destroying, don't duplicate work (return false, let first destroyer finish)
214 if (expected == LIFECYCLE_DESTROYING) {
215 log_dev("[lifecycle] destroy_once: already destroying, skipping (first destroyer has priority)");
216 return false;
217 }
218
219 // If initializing, skip destruction (init may still be in progress)
220 if (expected == LIFECYCLE_INITIALIZING) {
221 log_dev("[lifecycle] destroy_once: still initializing, skipping destruction");
222 return false;
223 }
224
225 // Unexpected state
226 log_dev("[lifecycle] destroy_once: unexpected state: %d", expected);
227 return false;
228 }
229
230 // Winner: state is now LIFECYCLE_DESTROYING
231 // Caller must call lifecycle_destroy_commit()
232 log_dev("[lifecycle] destroy_once: won CAS, transitioned to DESTROYING");
233 return true;
234}
235
237 if (lc == NULL) {
238 log_dev("[lifecycle] destroy_commit: NULL lifecycle pointer");
239 return;
240 }
241 log_dev("[lifecycle] destroy_commit: transitioning DESTROYING → UNINITIALIZED");
243}
bool atomic_cas_u64(atomic_t *a, uint64_t *expected, uint64_t new_value)
Atomically compare-and-swap a uint64_t.
Definition atomic.c:264
void atomic_store_u64(atomic_t *a, uint64_t value)
Atomically store a uint64_t value.
Definition atomic.c:241
uint64_t atomic_load_u64(atomic_t *a)
Atomically load a uint64_t value.
Definition atomic.c:233
⚛️ Atomic operations abstraction layer with debug tracking
unsigned long long uint64_t
Definition common.h:59
#define log_dev(...)
Log a DEV message (most verbose, development only)
Definition log/log.h:534
int rwlock_init(rwlock_t *rwlock, const char *name)
Initialize a read-write lock with a name.
Definition threading.c:65
int rwlock_destroy(rwlock_t *lock)
Destroy a read-write lock.
int mutex_init(mutex_t *mutex, const char *name)
Initialize a mutex with a name.
Definition threading.c:16
int mutex_destroy(mutex_t *mutex)
Destroy a mutex.
Definition threading.c:22
bool lifecycle_destroy_once(lifecycle_t *lc)
Definition lifecycle.c:193
void lifecycle_init_abort(lifecycle_t *lc)
Definition lifecycle.c:99
#define lifecycle_log_dev(...)
Definition lifecycle.c:17
bool lifecycle_shutdown_forever(lifecycle_t *lc)
Definition lifecycle.c:133
void lifecycle_destroy_commit(lifecycle_t *lc)
Definition lifecycle.c:236
bool lifecycle_is_initialized(const lifecycle_t *lc)
Definition lifecycle.c:155
void lifecycle_init_commit(lifecycle_t *lc)
Definition lifecycle.c:90
bool lifecycle_init(lifecycle_t *lc, const char *name)
Definition lifecycle.c:26
bool lifecycle_reset(lifecycle_t *lc)
Definition lifecycle.c:167
bool lifecycle_is_dead(const lifecycle_t *lc)
Definition lifecycle.c:161
bool lifecycle_shutdown(lifecycle_t *lc)
Definition lifecycle.c:108
bool lifecycle_init_once(lifecycle_t *lc)
Definition lifecycle.c:52
Lock-free module lifecycle state machine using pure stdatomic.
@ LIFECYCLE_SYNC_MUTEX
Contains mutex_t pointer.
Definition lifecycle.h:50
@ LIFECYCLE_SYNC_RWLOCK
Contains rwlock_t pointer.
Definition lifecycle.h:51
@ LIFECYCLE_DESTROYING
destroy_once winner in progress; losers skip
Definition lifecycle.h:45
@ LIFECYCLE_INITIALIZING
init_once winner in progress; losers spin
Definition lifecycle.h:42
@ LIFECYCLE_INITIALIZED
Ready to use.
Definition lifecycle.h:43
@ LIFECYCLE_DEAD
Permanently shut down; no re-init.
Definition lifecycle.h:44
@ LIFECYCLE_UNINITIALIZED
Not yet initialized (zero = default)
Definition lifecycle.h:41
📝 Logging API with multiple log levels and terminal output control
Cross-platform mutex interface for ascii-chat.
union lifecycle_t::@24 sync
rwlock_t * rwlock
Pointer to rwlock (if sync_type == LIFECYCLE_SYNC_RWLOCK)
Definition lifecycle.h:63
atomic_t state
lifecycle_state_t enum value
Definition lifecycle.h:59
mutex_t * mutex
Pointer to mutex (if sync_type == LIFECYCLE_SYNC_MUTEX)
Definition lifecycle.h:62
lifecycle_sync_type_t sync_type
Type of sync primitive (if any)
Definition lifecycle.h:60