ascii-chat 0.6.0
Real-time terminal-based video chat with ASCII art conversion
Loading...
Searching...
No Matches
init.h
Go to the documentation of this file.
1#pragma once
2
18
19// ============================================================================
20// Static Initialization Helpers
21// ============================================================================
22
23// Since Windows doesn't support static initialization of synchronization
24// primitives the same way POSIX does, we need a different approach.
25// We'll use a combination of static initialization and lazy initialization.
26
40typedef struct {
43#if PLATFORM_WINDOWS
45 volatile LONG initialized;
46#else
48 volatile int initialized;
49#endif
51
64typedef struct {
67#if PLATFORM_WINDOWS
69 volatile LONG initialized;
70#else
72 volatile int initialized;
73#endif
75
88typedef struct {
91#if PLATFORM_WINDOWS
93 volatile LONG initialized;
94#else
96 volatile int initialized;
97#endif
99
100// Initialization macros
101// clang-format off
102#if PLATFORM_WINDOWS
103#define STATIC_MUTEX_INIT {{0}, 0}
104#define STATIC_RWLOCK_INIT {{0}, 0}
105#define STATIC_COND_INIT {{0}, 0}
106#else
107#define STATIC_MUTEX_INIT {PTHREAD_MUTEX_INITIALIZER, 1}
108#define STATIC_RWLOCK_INIT {PTHREAD_RWLOCK_INITIALIZER, 1}
109#define STATIC_COND_INIT {PTHREAD_COND_INITIALIZER, 1}
110#endif
111// clang-format on
112
113// Lazy initialization functions
114static inline void static_mutex_lock(static_mutex_t *m) {
115#if PLATFORM_WINDOWS
116 // Use InterlockedCompareExchange for thread-safe lazy init with proper synchronization
117 // Pattern: First thread sets flag to 1, initializes, then sets to 2
118 // Other threads spin until flag is 2 (fully initialized)
119 LONG prev = InterlockedCompareExchange(&m->initialized, 1, 0);
120 if (prev == 0) {
121 // We won the race - initialize the mutex
122 mutex_init(&m->mutex);
123 // Memory barrier to ensure init is visible before flag update
124 MemoryBarrier();
125 InterlockedExchange(&m->initialized, 2);
126 } else if (prev == 1) {
127 // Another thread is initializing - spin until done
128 while (InterlockedCompareExchange(&m->initialized, 2, 2) != 2) {
129 YieldProcessor();
130 }
131 }
132 // prev == 2 means already initialized, proceed directly
133#endif
134 mutex_lock(&m->mutex);
135}
136
137static inline void static_mutex_unlock(static_mutex_t *m) {
138 mutex_unlock(&m->mutex);
139}
140
141static inline void static_rwlock_rdlock(static_rwlock_t *l) {
142#if PLATFORM_WINDOWS
143 LONG prev = InterlockedCompareExchange(&l->initialized, 1, 0);
144 if (prev == 0) {
145 rwlock_init(&l->lock);
146 MemoryBarrier();
147 InterlockedExchange(&l->initialized, 2);
148 } else if (prev == 1) {
149 while (InterlockedCompareExchange(&l->initialized, 2, 2) != 2) {
150 YieldProcessor();
151 }
152 }
153#endif
154 rwlock_rdlock(&l->lock);
155}
156
157static inline void static_rwlock_wrlock(static_rwlock_t *l) {
158#if PLATFORM_WINDOWS
159 LONG prev = InterlockedCompareExchange(&l->initialized, 1, 0);
160 if (prev == 0) {
161 rwlock_init(&l->lock);
162 MemoryBarrier();
163 InterlockedExchange(&l->initialized, 2);
164 } else if (prev == 1) {
165 while (InterlockedCompareExchange(&l->initialized, 2, 2) != 2) {
166 YieldProcessor();
167 }
168 }
169#endif
170 rwlock_wrlock(&l->lock);
171}
172
173static inline void static_cond_wait(static_cond_t *c, static_mutex_t *m) {
174#if PLATFORM_WINDOWS
175 LONG prev = InterlockedCompareExchange(&c->initialized, 1, 0);
176 if (prev == 0) {
177 cond_init(&c->cond);
178 MemoryBarrier();
179 InterlockedExchange(&c->initialized, 2);
180 } else if (prev == 1) {
181 while (InterlockedCompareExchange(&c->initialized, 2, 2) != 2) {
182 YieldProcessor();
183 }
184 }
185 if (InterlockedCompareExchange(&m->initialized, 1, 0) == 0) {
186 mutex_init(&m->mutex);
187 }
188#endif
189 cond_wait(&c->cond, &m->mutex);
190}
191
192static inline void static_cond_timedwait(static_cond_t *c, static_mutex_t *m, int timeout_ms) {
193#if PLATFORM_WINDOWS
194 LONG prev = InterlockedCompareExchange(&c->initialized, 1, 0);
195 if (prev == 0) {
196 cond_init(&c->cond);
197 MemoryBarrier();
198 InterlockedExchange(&c->initialized, 2);
199 } else if (prev == 1) {
200 while (InterlockedCompareExchange(&c->initialized, 2, 2) != 2) {
201 YieldProcessor();
202 }
203 }
204 if (InterlockedCompareExchange(&m->initialized, 1, 0) == 0) {
205 mutex_init(&m->mutex);
206 }
207#endif
208 cond_timedwait(&c->cond, &m->mutex, timeout_ms);
209}
210
211static inline void static_cond_signal(static_cond_t *c) {
212#if PLATFORM_WINDOWS
213 LONG prev = InterlockedCompareExchange(&c->initialized, 1, 0);
214 if (prev == 0) {
215 cond_init(&c->cond);
216 MemoryBarrier();
217 InterlockedExchange(&c->initialized, 2);
218 } else if (prev == 1) {
219 while (InterlockedCompareExchange(&c->initialized, 2, 2) != 2) {
220 YieldProcessor();
221 }
222 }
223#endif
224 cond_signal(&c->cond);
225}
226
227static inline void static_cond_broadcast(static_cond_t *c) {
228#if PLATFORM_WINDOWS
229 LONG prev = InterlockedCompareExchange(&c->initialized, 1, 0);
230 if (prev == 0) {
231 cond_init(&c->cond);
232 MemoryBarrier();
233 InterlockedExchange(&c->initialized, 2);
234 } else if (prev == 1) {
235 while (InterlockedCompareExchange(&c->initialized, 2, 2) != 2) {
236 YieldProcessor();
237 }
238 }
239#endif
240 cond_broadcast(&c->cond);
241}
242
243// ============================================================================
244// Platform Initialization
245// ============================================================================
246
247// Call this once at program startup
249
250// Call this at program exit
252
🔌 Cross-platform abstraction layer umbrella header for ascii-chat
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:46
int mutex_init(mutex_t *mutex)
Initialize a mutex.
int cond_init(cond_t *cond)
Initialize a condition variable.
void platform_cleanup(void)
Cleanup platform-specific subsystems.
int cond_timedwait(cond_t *cond, mutex_t *mutex, int timeout_ms)
Wait on a condition variable with timeout.
#define mutex_lock(mutex)
Lock a mutex (with debug tracking in debug builds)
Definition mutex.h:140
int cond_broadcast(cond_t *cond)
Broadcast to a condition variable (wake all waiting threads)
pthread_mutex_t mutex_t
Mutex type (POSIX: pthread_mutex_t)
Definition mutex.h:38
#define rwlock_rdlock(lock)
Acquire a read lock (with debug tracking in debug builds)
Definition rwlock.h:194
int cond_signal(cond_t *cond)
Signal a condition variable (wake one waiting thread)
pthread_rwlock_t rwlock_t
Read-write lock type (POSIX: pthread_rwlock_t)
Definition rwlock.h:40
#define rwlock_wrlock(lock)
Acquire a write lock (with debug tracking in debug builds)
Definition rwlock.h:213
pthread_cond_t cond_t
Condition variable type (POSIX: pthread_cond_t)
Definition cond.h:38
#define mutex_unlock(mutex)
Unlock a mutex (with debug tracking in debug builds)
Definition mutex.h:175
int cond_wait(cond_t *cond, mutex_t *mutex)
Wait on a condition variable (blocking)
asciichat_error_t platform_init(void)
Initialize platform-specific subsystems.
int rwlock_init(rwlock_t *lock)
Initialize a read-write lock.
bool initialized
Definition mmap.c:36
Static condition variable structure for global condition variables requiring static initialization.
Definition init.h:88
volatile int initialized
Thread-safe initialization flag (POSIX: int for atomic operations)
Definition init.h:96
cond_t cond
The actual condition variable.
Definition init.h:90
Static mutex structure for global mutexes requiring static initialization.
Definition init.h:40
volatile int initialized
Thread-safe initialization flag (POSIX: int for atomic operations)
Definition init.h:48
mutex_t mutex
The actual mutex.
Definition init.h:42
Static reader-writer lock structure for global rwlocks requiring static initialization.
Definition init.h:64
rwlock_t lock
The actual reader-writer lock.
Definition init.h:66
volatile int initialized
Thread-safe initialization flag (POSIX: int for atomic operations)
Definition init.h:72