41#if defined(__cplusplus) && defined(_WIN32)
43using std::atomic_bool;
44using std::atomic_uint_fast32_t;
45using std::atomic_uint_fast64_t;
72#define MAX_LOCK_RECORDS 1024
73#define MAX_BACKTRACE_FRAMES 32
74#define MAX_FUNCTION_NAME_LEN 256
75#define MAX_FILE_NAME_LEN 256
87 LOCK_TYPE_RWLOCK_READ,
88 LOCK_TYPE_RWLOCK_WRITE
95typedef struct lock_record lock_record_t;
115 lock_type_t lock_type;
117 struct timespec acquisition_time;
118 const char *file_name;
120 const char *function_name;
123 void *backtrace_buffer[MAX_BACKTRACE_FRAMES];
125 char **backtrace_symbols;
127 UT_hash_handle hash_handle;
142typedef struct lock_usage_stats {
144 const char *file_name;
146 const char *function_name;
147 lock_type_t lock_type;
152 struct timespec first_acquisition;
153 struct timespec last_acquisition;
154 UT_hash_handle hash_handle;
172typedef struct lock_debug_manager {
174 lock_record_t *lock_records;
175 lock_usage_stats_t *usage_stats;
176 lock_record_t *orphaned_releases;
184 atomic_uint_fast64_t total_locks_acquired;
185 atomic_uint_fast64_t total_locks_released;
186 atomic_uint_fast32_t current_locks_held;
190 atomic_bool debug_thread_running;
191 atomic_bool debug_thread_created;
192 atomic_bool should_print_locks;
196} lock_debug_manager_t;
202extern lock_debug_manager_t g_lock_debug_manager;
203extern atomic_bool g_initializing;
221static inline uint32_t lock_record_key(
void *lock_address, lock_type_t lock_type) {
227 lock_type_t lock_type;
230 return fnv1a_hash_bytes(&key_data,
sizeof(key_data));
241static inline uint32_t usage_stats_key(
const char *file_name,
int line_number,
const char *function_name,
242 lock_type_t lock_type) {
244 uint32_t hash = fnv1a_hash_string(file_name);
245 hash = fnv1a_hash_bytes(&line_number,
sizeof(line_number)) ^ hash;
246 hash = fnv1a_hash_string(function_name) ^ hash;
247 hash = fnv1a_hash_bytes(&lock_type,
sizeof(lock_type)) ^ hash;
260int lock_debug_init(
void);
267int lock_debug_start_thread(
void);
273void lock_debug_cleanup(
void);
279void lock_debug_cleanup_thread(
void);
285void lock_debug_trigger_print(
void);
375#define DEBUG_MUTEX_LOCK(mutex) debug_mutex_lock(mutex, __FILE__, __LINE__, __func__)
376#define DEBUG_MUTEX_UNLOCK(mutex) debug_mutex_unlock(mutex, __FILE__, __LINE__, __func__)
377#define DEBUG_RWLOCK_RDLOCK(rwlock) debug_rwlock_rdlock(rwlock, __FILE__, __LINE__, __func__)
378#define DEBUG_RWLOCK_WRLOCK(rwlock) debug_rwlock_wrlock(rwlock, __FILE__, __LINE__, __func__)
380#define DEBUG_MUTEX_LOCK(mutex) debug_mutex_lock(mutex, NULL, 0, NULL)
381#define DEBUG_MUTEX_UNLOCK(mutex) debug_mutex_unlock(mutex, NULL, 0, NULL)
382#define DEBUG_RWLOCK_RDLOCK(rwlock) debug_rwlock_rdlock(rwlock, NULL, 0, NULL)
383#define DEBUG_RWLOCK_WRLOCK(rwlock) debug_rwlock_wrlock(rwlock, NULL, 0, NULL)
415void lock_debug_print_state(
void);
423void print_orphaned_release_callback(lock_record_t *record,
void *user_data);
#️⃣ FNV-1a Hash Function Implementation
unsigned long long uint64_t
uint64_t asciichat_thread_current_id(void)
Cross-platform mutex interface for ascii-chat.
Cross-platform read-write lock interface for ascii-chat.
rwlock_t rwlock
Read-write lock for thread-safe access (uthash requires external locking)
⏱️ High-precision timing utilities using sokol_time.h and uthash
#️⃣ Wrapper for uthash.h that ensures common.h is included first