ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
rwlock.c
Go to the documentation of this file.
1
14#include <ascii-chat/atomic.h>
15#include <ascii-chat/log/log.h>
16#include <stdio.h>
17
18#ifndef NDEBUG
19
36
54
65 if (!rwlock)
66 return;
70 uintptr_t current_key = asciichat_thread_to_key(current_thread);
71 if (rwlock->write_held_by_key == current_key) {
73 } else if (atomic_load_u64(&rwlock->read_lock_count) > 0) {
75 }
76}
77
90int rwlock_format_state(const rwlock_t *rwlock, char *buffer, size_t size) {
91 if (!rwlock || !buffer || size == 0)
92 return 0;
93
94 int offset = 0;
95 uint64_t now_ns = time_get_ns();
96
97 char rdlock_str[64] = "";
98 char wrlock_str[64] = "";
99 char unlock_str[64] = "";
100 char held_str[64] = "";
101 char count_str[256] = "";
102
103 if (rwlock->last_rdlock_time_ns > 0 && rwlock->last_rdlock_time_ns <= now_ns) {
104 char elapsed_str[64];
105 time_pretty(now_ns - rwlock->last_rdlock_time_ns, -1, elapsed_str, sizeof(elapsed_str));
106 snprintf(rdlock_str, sizeof(rdlock_str), "rdlock=%s", elapsed_str);
107 }
108
109 if (rwlock->last_wrlock_time_ns > 0 && rwlock->last_wrlock_time_ns <= now_ns) {
110 char elapsed_str[64];
111 time_pretty(now_ns - rwlock->last_wrlock_time_ns, -1, elapsed_str, sizeof(elapsed_str));
112 snprintf(wrlock_str, sizeof(wrlock_str), "wrlock=%s", elapsed_str);
113 }
114
115 if (rwlock->last_unlock_time_ns > 0 && rwlock->last_unlock_time_ns <= now_ns) {
116 char elapsed_str[64];
117 time_pretty(now_ns - rwlock->last_unlock_time_ns, -1, elapsed_str, sizeof(elapsed_str));
118 snprintf(unlock_str, sizeof(unlock_str), "unlock=%s", elapsed_str);
119 }
120
122 if (rwlock->write_held_by_key != 0) {
123 snprintf(held_str, sizeof(held_str), "[WRITE_LOCKED_BY=thread.%lu]", (unsigned long)rwlock->write_held_by_key);
124 } else if (read_count > 0) {
125 snprintf(held_str, sizeof(held_str), "[READ_LOCKED=%llu]", (unsigned long long)read_count);
126 }
127
128 if (rwlock->rdlock_count > 0 || rwlock->wrlock_count > 0 || rwlock->unlock_count > 0) {
129 snprintf(count_str, sizeof(count_str), "[ops: rdlock=%llu wrlock=%llu unlock=%llu]",
130 (unsigned long long)rwlock->rdlock_count, (unsigned long long)rwlock->wrlock_count,
131 (unsigned long long)rwlock->unlock_count);
132 }
133
134 offset += snprintf(buffer + offset, size - offset, "%s %s %s %s %s", rdlock_str, wrlock_str, unlock_str, held_str,
135 count_str);
136 return offset;
137}
138
150void rwlock_log_state(const rwlock_t *rwlock, const char *file, int line, const char *func) {
151 if (!rwlock)
152 return;
153 char buf[512];
154 rwlock_format_state(rwlock, buf, sizeof(buf));
155 log_msg(LOG_DEBUG, file, line, func, "rwlock/state %p: %s", (const void *)rwlock, buf);
156}
157
158#endif // !NDEBUG
uint64_t atomic_fetch_add_u64(atomic_t *a, uint64_t delta)
Atomically add to a uint64_t and return the previous value.
Definition atomic.c:248
uint64_t atomic_fetch_sub_u64(atomic_t *a, uint64_t delta)
Atomically subtract from a uint64_t and return the previous value.
Definition atomic.c:256
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
uintptr_t asciichat_thread_to_key(asciichat_thread_t thread)
Convert a thread handle to a registry key.
Definition threading.c:87
void log_msg(log_level_t level, const char *file, int line, const char *func, const char *fmt,...)
Log a message at a specific level.
Definition log/log.c:1019
uint64_t time_get_ns(void)
Get current monotonic time in nanoseconds.
Definition util/time.c:108
int time_pretty(uint64_t nanoseconds, int decimals, char *buffer, size_t buffer_size)
Format nanoseconds as pretty duration with spaces and configurable precision.
Definition util/time.c:424
uint64_t wrlock_count
Total write lock acquisitions.
Definition rwlock.h:71
void rwlock_log_state(const rwlock_t *rwlock, const char *file, int line, const char *func)
Log the state of a read-write lock.
Definition rwlock.c:150
int rwlock_format_state(const rwlock_t *rwlock, char *buffer, size_t size)
Format rwlock timing and state info into buffer.
Definition rwlock.c:90
void rwlock_on_unlock(rwlock_t *rwlock)
Hook called when an rwlock is unlocked (read or write)
Definition rwlock.c:64
uintptr_t write_held_by_key
Registry key of thread holding write lock (0 if not held)
Definition rwlock.h:68
uint64_t last_unlock_time_ns
Timestamp of last unlock (nanoseconds)
Definition rwlock.h:67
void rwlock_on_rdlock(rwlock_t *rwlock)
Hook called when a read lock is successfully acquired.
Definition rwlock.c:29
uint64_t unlock_count
Total unlocks.
Definition rwlock.h:72
uint64_t last_wrlock_time_ns
Timestamp of last write lock acquisition (nanoseconds)
Definition rwlock.h:66
void rwlock_on_wrlock(rwlock_t *rwlock)
Hook called when a write lock is successfully acquired.
Definition rwlock.c:46
uint64_t last_rdlock_time_ns
Timestamp of last read lock acquisition (nanoseconds)
Definition rwlock.h:65
uint64_t rdlock_count
Total read lock acquisitions.
Definition rwlock.h:70
uint64_t asciichat_thread_current_id(void)
Get the current thread's unique numeric ID.
Definition threading.c:92
atomic_t read_lock_count
Number of threads holding read locks (thread-safe atomic)
Definition rwlock.h:69
🧵 Cross-platform thread interface for ascii-chat
void * asciichat_thread_t
📝 Logging API with multiple log levels and terminal output control
Cross-platform read-write lock interface for ascii-chat.
Read-write lock type (POSIX: pthread_rwlock_t with debug tracking)
Definition rwlock.h:61
⏱️ High-precision timing utilities using sokol_time.h and uthash
#define LOG_DEBUG
Definition types.h:39
rwlock_t rwlock
Read-write lock for thread-safe access (uthash requires external locking)
Definition util/time.c:34