ascii-chat 0.11.33
Video chat in your terminal
Loading...
Searching...
No Matches
time.h
Go to the documentation of this file.
1#pragma once
2
36#include <stdint.h>
37#include <stdbool.h>
38#include <time.h>
39// C11 stdatomic.h conflicts with MSVC's C++ <atomic> header on Windows.
40// Include the appropriate header based on the compilation mode.
41#if defined(__cplusplus) && defined(_WIN32)
42#include <atomic>
43using std::atomic_compare_exchange_weak_explicit;
44using std::atomic_load_explicit;
45using std::memory_order_relaxed;
46// C11 _Atomic(T) syntax doesn't work in C++ - use std::atomic<T> instead
47#define TIME_ATOMIC_UINT64 std::atomic<uint64_t>
48#define TIME_ATOMIC_UINT64_INIT(val) {val}
49#else
50#include <ascii-chat/atomic.h>
51// Use atomic_t for rate-limiting counters
52#define TIME_ATOMIC_UINT64 atomic_t
53#define TIME_ATOMIC_UINT64_INIT(val) {0}
54#endif
55
56// ============================================================================
57// sokol_time.h Integration
58// ============================================================================
59
60// Include sokol_time.h declarations (WITHOUT implementation)
61// SOKOL_TIME_IMPL is defined only in time.c to avoid duplicate symbols
62#include <ascii-chat-deps/sokol/sokol_time.h>
63
64// Include platform thread for thread ID in timer names
65#include "../platform/thread.h"
66
67// Include uthash wrapper for UBSan-safe hash functions
68// Headers can include this even before common.h is fully processed
69#include <ascii-chat/uthash.h>
70
71// ============================================================================
72// Core Monotonic Timing API (Nanosecond Precision)
73// ============================================================================
74
92
107
118void time_sleep_ns(uint64_t ns);
119
139uint64_t time_elapsed_ns(uint64_t start_ns, uint64_t end_ns);
140
141// ============================================================================
142// Time Unit Constants (moved before inline functions that use them)
143// ============================================================================
144
145// Floating-point versions (for time formatting and conversions)
146#define NS_PER_US 1000.0
147#define NS_PER_MS (1000.0 * NS_PER_US)
148#define NS_PER_SEC (1000.0 * NS_PER_MS)
149#define NS_PER_MIN (60.0 * NS_PER_SEC)
150#define NS_PER_HOUR (60.0 * NS_PER_MIN)
151#define NS_PER_DAY (24.0 * NS_PER_HOUR)
152#define NS_PER_YEAR (365.25 * NS_PER_DAY) // Account for leap years
153
154// Integer versions (for comparing uint64_t nanosecond values)
155#define NS_PER_US_INT 1000ULL
156#define NS_PER_MS_INT (1000ULL * NS_PER_US_INT)
157#define NS_PER_SEC_INT (1000ULL * NS_PER_MS_INT)
158
159// Microsecond versions (for API compatibility)
160#define US_PER_MS_INT 1000ULL
161#define US_PER_SEC_INT 1000000ULL
162
163// Millisecond versions (for API compatibility)
164#define MS_PER_SEC_INT 1000ULL
165
166// Standard time unit conversions (seconds-based)
167#define SEC_PER_MIN 60ULL
168#define SEC_PER_HOUR (SEC_PER_MIN * SEC_PER_MIN)
169#define SEC_PER_DAY (24ULL * SEC_PER_HOUR)
170
171// Minute/hour/day to nanoseconds conversions
172#define NS_PER_MIN_INT (SEC_PER_MIN * NS_PER_SEC_INT)
173#define NS_PER_HOUR_INT (SEC_PER_HOUR * NS_PER_SEC_INT)
174#define NS_PER_DAY_INT (SEC_PER_DAY * NS_PER_SEC_INT)
175
176// ============================================================================
177// Inline Time Conversion Helpers
178// ============================================================================
179
186static inline uint64_t time_ns_to_us(uint64_t ns) {
187 return ns / NS_PER_US_INT;
188}
189
196static inline uint64_t time_ns_to_ms(uint64_t ns) {
197 return ns / NS_PER_MS_INT;
198}
199
206static inline double time_ns_to_s(uint64_t ns) {
207 return (double)ns / 1e9;
208}
209
216static inline uint64_t time_us_to_ns(uint64_t us) {
217 return us * NS_PER_US_INT;
218}
219
226static inline uint64_t time_ms_to_ns(uint64_t ms) {
227 return ms * NS_PER_MS_INT;
228}
229
236static inline uint64_t time_s_to_ns(double s) {
237 return (uint64_t)(s * 1e9);
238}
239
240// ============================================================================
241// Timer Record Structure
242// ============================================================================
243
248typedef struct timer_record {
249 char *name;
251 UT_hash_handle hh;
253
254// ============================================================================
255// Timer System API
256// ============================================================================
257
267bool timer_system_init(void);
268
277void timer_system_destroy(void);
278
289bool timer_start(const char *name);
290
301double timer_stop(const char *name);
302
309bool timer_is_initialized(void);
310
311// ============================================================================
312// Convenience Macros
313// ============================================================================
314
333#define START_TIMER(name_fmt, ...) \
334 do { \
335 if (timer_is_initialized()) { \
336 char _timer_name_buf[256]; \
337 char _timer_name_with_tid[280]; \
338 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
339 snprintf(_timer_name_with_tid, sizeof(_timer_name_with_tid), "%s_tid%llu", _timer_name_buf, \
340 (unsigned long long)asciichat_thread_current_id()); \
341 (void)timer_start(_timer_name_with_tid); \
342 } \
343 } while (0)
344
357#define START_TIMER_GLOBAL(name_fmt, ...) \
358 do { \
359 if (timer_is_initialized()) { \
360 char _timer_name_buf[256]; \
361 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
362 (void)timer_start(_timer_name_buf); \
363 } \
364 } while (0)
365
377#define STOP_TIMER_GLOBAL(name_fmt, ...) \
378 ({ \
379 double _elapsed = -1.0; \
380 if (timer_is_initialized()) { \
381 char _timer_name_buf[256]; \
382 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
383 _elapsed = timer_stop(_timer_name_buf); \
384 } \
385 _elapsed; \
386 })
387
403#define STOP_TIMER(name_fmt, ...) \
404 ({ \
405 double _elapsed = -1.0; \
406 if (timer_is_initialized()) { \
407 char _timer_name_buf[256]; \
408 char _timer_name_with_tid[280]; \
409 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
410 snprintf(_timer_name_with_tid, sizeof(_timer_name_with_tid), "%s_tid%llu", _timer_name_buf, \
411 (unsigned long long)asciichat_thread_current_id()); \
412 _elapsed = timer_stop(_timer_name_with_tid); \
413 } \
414 _elapsed; \
415 })
416
417// ============================================================================
418// Time Formatting API
419// ============================================================================
420
421
456int time_pretty(uint64_t nanoseconds, int decimals, char *buffer, size_t buffer_size);
457
473int time_pretty_now(int decimals, char *buffer, size_t buffer_size);
474
523int time_human_readable(int64_t nanoseconds, char *buffer, size_t buffer_size);
524
546int time_human_readable_unsigned(uint64_t nanoseconds, char *buffer, size_t buffer_size);
547
562int time_human_readable_now(char *buffer, size_t buffer_size);
563
588int format_uptime_hms(int hours, int minutes, int seconds, char *buffer, size_t buffer_size);
589
612#define STOP_TIMER_AND_LOG(log_level, threshold_ns, timer_name, msg_fmt, ...) \
613 do { \
614 double _elapsed_ns = STOP_TIMER(timer_name, ##__VA_ARGS__); \
615 if (_elapsed_ns >= 0.0 && (threshold_ns == 0 || _elapsed_ns >= (double)(threshold_ns))) { \
616 char _duration_str[32]; \
617 time_pretty((uint64_t)_elapsed_ns, -1, _duration_str, sizeof(_duration_str)); \
618 log_##log_level(msg_fmt " in %s", ##__VA_ARGS__, _duration_str); \
619 } \
620 } while (0)
621
647#define STOP_TIMER_AND_LOG_EVERY(log_level, interval_ns, threshold_ns, timer_name, msg_fmt, ...) \
648 do { \
649 double _elapsed_ns = STOP_TIMER(timer_name, ##__VA_ARGS__); \
650 if (_elapsed_ns >= 0.0 && (threshold_ns == 0 || _elapsed_ns >= (double)(threshold_ns))) { \
651 static atomic_t _log_every_last_time = {0}; \
652 uint64_t _log_every_now = time_get_ns(); \
653 uint64_t _log_every_last = atomic_load_u64(&_log_every_last_time); \
654 if (_log_every_now - _log_every_last >= (uint64_t)(interval_ns)) { \
655 if (atomic_cas_u64(&_log_every_last_time, &_log_every_last, _log_every_now)) { \
656 char _duration_str[32]; \
657 time_pretty((uint64_t)_elapsed_ns, -1, _duration_str, sizeof(_duration_str)); \
658 log_##log_level(msg_fmt " in %s", ##__VA_ARGS__, _duration_str); \
659 } \
660 } \
661 } \
662 } while (0)
663
664// ============================================================================
665// Adaptive Sleep System
666// ============================================================================
667
684
698
711
751uint64_t adaptive_sleep_calculate(adaptive_sleep_state_t *state, size_t queue_depth, size_t target_depth);
752
764void adaptive_sleep_do(adaptive_sleep_state_t *state, size_t queue_depth, size_t target_depth);
765
766/* ============================================================================
767 * Time Format Validation and Formatting
768 * ============================================================================ */
769
794bool time_format_is_valid_strftime(const char *format_str);
795
820int time_format_now(const char *format_str, char *buf, size_t buf_size);
821
851asciichat_error_t time_format_safe(const char *format_str, char *buf, size_t buf_size);
852
855/* ============================================================================
856 * Conversion Functions
857 * ============================================================================ */
858
867uint64_t time_timespec_to_ns(const struct timespec *ts);
868
877void time_ns_to_timespec(uint64_t ns, struct timespec *ts);
⚛️ Atomic operations abstraction layer with debug tracking
int buffer_size
Size of circular buffer.
Definition grep.c:90
unsigned long long uint64_t
Definition common.h:59
asciichat_error_t
Error and exit codes - unified status values (0-255)
Definition error_codes.h:49
double timer_stop(const char *name)
Stop a named timer and return elapsed time.
Definition util/time.c:291
int time_pretty_now(int decimals, char *buffer, size_t buffer_size)
Format current monotonic time as pretty duration.
Definition util/time.c:540
bool timer_start(const char *name)
Start a named timer.
Definition util/time.c:240
bool time_format_is_valid_strftime(const char *format_str)
Validate strftime format string against known safe specifiers.
Definition util/time.c:711
uint64_t time_get_ns(void)
Get current monotonic time in nanoseconds.
Definition util/time.c:108
void time_ns_to_timespec(uint64_t ns, struct timespec *ts)
Convert nanoseconds to struct timespec.
Definition util/time.c:178
uint64_t time_get_realtime_ns(void)
Get current wall-clock (real) time in nanoseconds.
Definition util/time.c:119
uint64_t adaptive_sleep_calculate(adaptive_sleep_state_t *state, size_t queue_depth, size_t target_depth)
Calculate adaptive sleep time based on queue depth.
Definition util/time.c:630
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
int time_format_now(const char *format_str, char *buf, size_t buf_size)
Format current time using strftime format string.
Definition util/time.c:786
uint64_t time_timespec_to_ns(const struct timespec *ts)
Convert struct timespec to nanoseconds.
Definition util/time.c:164
void timer_system_destroy(void)
Cleanup the timing system.
Definition util/time.c:213
#define NS_PER_MS_INT
Definition time.h:156
int time_human_readable_unsigned(uint64_t nanoseconds, char *buffer, size_t buffer_size)
Format elapsed time as human-readable relative duration (unsigned version)
Definition util/time.c:549
void adaptive_sleep_init(adaptive_sleep_state_t *state, const adaptive_sleep_config_t *config)
Initialize adaptive sleep state with configuration.
Definition util/time.c:609
int time_human_readable(int64_t nanoseconds, char *buffer, size_t buffer_size)
Format nanoseconds as human-readable relative duration (moment.js style)
Definition util/time.c:572
uint64_t time_elapsed_ns(uint64_t start_ns, uint64_t end_ns)
Calculate elapsed time with wraparound safety.
Definition util/time.c:150
#define NS_PER_US_INT
Definition time.h:155
int format_uptime_hms(int hours, int minutes, int seconds, char *buffer, size_t buffer_size)
Format uptime as HH:MM:SS string.
Definition util/time.c:354
void time_sleep_ns(uint64_t ns)
Sleep for specified nanoseconds.
Definition util/time.c:140
bool timer_is_initialized(void)
Check if timing system is initialized.
Definition util/time.c:346
bool timer_system_init(void)
Initialize the timing system.
Definition util/time.c:191
void adaptive_sleep_do(adaptive_sleep_state_t *state, size_t queue_depth, size_t target_depth)
Calculate sleep time and immediately sleep for that duration.
Definition util/time.c:693
struct timer_record timer_record_t
Individual timer record for a named timing operation.
asciichat_error_t time_format_safe(const char *format_str, char *buf, size_t buf_size)
Safe wrapper for time formatting with validation and error codes.
Definition util/time.c:822
int time_human_readable_now(char *buffer, size_t buffer_size)
Format current monotonic time as human-readable relative duration.
Definition util/time.c:600
ClangTool/LibTooling compatibility shim for stdbool.h.
Configuration for adaptive sleep behavior.
Definition time.h:677
double min_speed_multiplier
Minimum speed (max sleep) - usually 1.0 (baseline speed)
Definition time.h:679
double max_speed_multiplier
Maximum speed (min sleep) - e.g., 4.0 = process 4x faster.
Definition time.h:680
uint64_t baseline_sleep_ns
Normal sleep time in nanoseconds (when queue is at target)
Definition time.h:678
double speedup_rate
Ramp-up rate when queue builds (0.0-1.0, higher = faster ramp)
Definition time.h:681
double slowdown_rate
Ramp-down rate when queue empties (0.0-1.0, higher = faster ramp)
Definition time.h:682
Runtime state for adaptive sleep.
Definition time.h:693
double current_speed_multiplier
Current speed state (1.0 = baseline, >1.0 = faster)
Definition time.h:695
uint64_t last_sleep_ns
Last calculated sleep time (for debugging)
Definition time.h:696
adaptive_sleep_config_t config
Configuration (copied, not referenced)
Definition time.h:694
Individual timer record for a named timing operation.
Definition time.h:248
uint64_t start_ticks
Start time in sokol ticks.
Definition time.h:250
char * name
Timer name (heap-allocated, unique key)
Definition time.h:249
UT_hash_handle hh
uthash handle (makes this hashable by name)
Definition time.h:251
⏱️ High-precision timing utilities using sokol_time.h and uthash