ascii-chat
Binary v0.15.83-53-gb711d8720
Library lib/v0.3.2-701-gb711d8720
Video chat in your terminal
Loading...
Searching...
No Matches
time.h
Go to the documentation of this file.
1#pragma once
3
5
38
39/* Storage capacities in elements; text buffers include the terminating NUL. */
40#define TIME_DURATION_BUFFER_SIZE 32
41
42/* Storage capacities in elements; text buffers include the terminating NUL. */
43#define UTIL_TIME_TIMER_NAME_BUFFER_SIZE 256
44#define UTIL_TIME_TIMER_NAME_WITH_TID_BUFFER_SIZE 280
45
46#include <stdint.h>
47#include <stdbool.h>
48#include <time.h>
49#include <libplatform/time.h>
50// C11 stdatomic.h conflicts with MSVC's C++ <atomic> header on Windows.
51// Include the appropriate header based on the compilation mode.
52#if defined(__cplusplus) && defined(_WIN32)
53#include <atomic>
54using std::atomic_compare_exchange_weak_explicit;
55using std::atomic_load_explicit;
56using std::memory_order_relaxed;
57// C11 _Atomic(T) syntax doesn't work in C++ - use std::atomic<T> instead
58#define TIME_ATOMIC_UINT64 std::atomic<uint64_t>
59#define TIME_ATOMIC_UINT64_INIT(val) {val}
60#else
61#include <libplatform/atomic.h>
62// Use atomic_t for rate-limiting counters
63#define TIME_ATOMIC_UINT64 atomic_t
64#define TIME_ATOMIC_UINT64_INIT(val) {0}
65#endif
66
67// ============================================================================
68// sokol_time.h Integration
69// ============================================================================
70
71// Include sokol_time.h declarations (WITHOUT implementation)
72// SOKOL_TIME_IMPL is defined only in time.c to avoid duplicate symbols
73#include <ascii-chat-deps/sokol/sokol_time.h>
74
75// Include platform thread for thread ID in timer names
76#include <libplatform/thread.h>
77
78// Include uthash wrapper for UBSan-safe hash functions
79// Headers can include this even before common.h is fully processed
80#include <ascii-chat/uthash.h>
81
82// ============================================================================
83// Core Monotonic Timing API (Nanosecond Precision)
84// ============================================================================
85
105
119
130void time_sleep_ns(uint64_t ns);
131
151uint64_t time_elapsed_ns(uint64_t start_ns, uint64_t end_ns);
152
153// ============================================================================
154// Time Unit Constants (moved before inline functions that use them)
155// ============================================================================
156
157// Floating-point versions (for time formatting and conversions)
158#define NS_PER_US 1000.0
159#define NS_PER_MS (1000.0 * NS_PER_US)
160#define NS_PER_SEC (1000.0 * NS_PER_MS)
161#define NS_PER_MIN (60.0 * NS_PER_SEC)
162#define NS_PER_HOUR (60.0 * NS_PER_MIN)
163#define NS_PER_DAY (24.0 * NS_PER_HOUR)
164#define NS_PER_YEAR (365.25 * NS_PER_DAY) // Account for leap years
165
166// Integer versions (for comparing uint64_t nanosecond values)
167#define NS_PER_US_INT 1000ULL
168#define NS_PER_MS_INT (1000ULL * NS_PER_US_INT)
169#define NS_PER_SEC_INT (1000ULL * NS_PER_MS_INT)
170
171// Microsecond versions (for API compatibility)
172#define US_PER_MS_INT 1000ULL
173#define US_PER_SEC_INT 1000000ULL
174
175// Millisecond versions (for API compatibility)
176#define MS_PER_SEC_INT 1000ULL
177
178// Standard time unit conversions (seconds-based)
179#define SEC_PER_MIN 60ULL
180#define SEC_PER_HOUR (SEC_PER_MIN * SEC_PER_MIN)
181#define SEC_PER_DAY (24ULL * SEC_PER_HOUR)
182
183// Minute/hour/day to nanoseconds conversions
184#define NS_PER_MIN_INT (SEC_PER_MIN * NS_PER_SEC_INT)
185#define NS_PER_HOUR_INT (SEC_PER_HOUR * NS_PER_SEC_INT)
186#define NS_PER_DAY_INT (SEC_PER_DAY * NS_PER_SEC_INT)
187
188// ============================================================================
189// Inline Time Conversion Helpers
190// ============================================================================
191
198static inline uint64_t time_ns_to_us(uint64_t ns) {
199 return ns / NS_PER_US_INT;
200}
201
208static inline uint64_t time_ns_to_ms(uint64_t ns) {
209 return ns / NS_PER_MS_INT;
210}
211
218static inline double time_ns_to_s(uint64_t ns) {
219 return (double)ns / 1e9;
220}
221
228static inline uint64_t time_us_to_ns(uint64_t us) {
229 return us * NS_PER_US_INT;
230}
231
238static inline uint64_t time_ms_to_ns(uint64_t ms) {
239 return ms * NS_PER_MS_INT;
240}
241
248static inline uint64_t time_s_to_ns(double s) {
249 return (uint64_t)(s * 1e9);
250}
251
252// ============================================================================
253// Timer Record Structure
254// ============================================================================
255
260typedef struct timer_record {
261 char *name;
263 UT_hash_handle hh;
265
266// ============================================================================
267// Timer System API
268// ============================================================================
269
279bool timer_system_init(void);
280
289void timer_system_destroy(void);
290
301bool timer_start(const char *name);
302
313double timer_stop(const char *name);
314
321bool timer_is_initialized(void);
322
323// ============================================================================
324// Convenience Macros
325// ============================================================================
326
345#define START_TIMER(name_fmt, ...) \
346 do { \
347 if (timer_is_initialized()) { \
348 char _timer_name_buf[UTIL_TIME_TIMER_NAME_BUFFER_SIZE]; \
349 char _timer_name_with_tid[UTIL_TIME_TIMER_NAME_WITH_TID_BUFFER_SIZE]; \
350 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
351 snprintf(_timer_name_with_tid, sizeof(_timer_name_with_tid), "%s_tid%llu", _timer_name_buf, \
352 (unsigned long long)thread_current_id()); \
353 (void)timer_start(_timer_name_with_tid); \
354 } \
355 } while (0)
356
369#define START_TIMER_GLOBAL(name_fmt, ...) \
370 do { \
371 if (timer_is_initialized()) { \
372 char _timer_name_buf[UTIL_TIME_TIMER_NAME_BUFFER_SIZE]; \
373 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
374 (void)timer_start(_timer_name_buf); \
375 } \
376 } while (0)
377
389#define STOP_TIMER_GLOBAL(name_fmt, ...) \
390 ({ \
391 double _elapsed = -1.0; \
392 if (timer_is_initialized()) { \
393 char _timer_name_buf[UTIL_TIME_TIMER_NAME_BUFFER_SIZE]; \
394 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
395 _elapsed = timer_stop(_timer_name_buf); \
396 } \
397 _elapsed; \
398 })
399
415#define STOP_TIMER(name_fmt, ...) \
416 ({ \
417 double _elapsed = -1.0; \
418 if (timer_is_initialized()) { \
419 char _timer_name_buf[UTIL_TIME_TIMER_NAME_BUFFER_SIZE]; \
420 char _timer_name_with_tid[UTIL_TIME_TIMER_NAME_WITH_TID_BUFFER_SIZE]; \
421 snprintf(_timer_name_buf, sizeof(_timer_name_buf), name_fmt, ##__VA_ARGS__); \
422 snprintf(_timer_name_with_tid, sizeof(_timer_name_with_tid), "%s_tid%llu", _timer_name_buf, \
423 (unsigned long long)thread_current_id()); \
424 _elapsed = timer_stop(_timer_name_with_tid); \
425 } \
426 _elapsed; \
427 })
428
429// ============================================================================
430// Time Formatting API
431// ============================================================================
432
470int time_pretty(uint64_t nanoseconds, int decimals, char *buffer, size_t buffer_size);
471
487int time_pretty_now(int decimals, char *buffer, size_t buffer_size);
488
537int time_human_readable(int64_t nanoseconds, char *buffer, size_t buffer_size);
538
560int time_human_readable_unsigned(uint64_t nanoseconds, char *buffer, size_t buffer_size);
561
576int time_human_readable_now(char *buffer, size_t buffer_size);
577
602int format_uptime_hms(int hours, int minutes, int seconds, char *buffer, size_t buffer_size);
603
626#define STOP_TIMER_AND_LOG(log_level, threshold_ns, timer_name, msg_fmt, ...) \
627 do { \
628 double _elapsed_ns = STOP_TIMER(timer_name, ##__VA_ARGS__); \
629 if (_elapsed_ns >= 0.0 && (threshold_ns == 0 || _elapsed_ns >= (double)(threshold_ns))) { \
630 char _duration_str[TIME_DURATION_BUFFER_SIZE]; \
631 time_pretty((uint64_t)_elapsed_ns, -1, _duration_str, sizeof(_duration_str)); \
632 log_##log_level(msg_fmt " in %s", ##__VA_ARGS__, _duration_str); \
633 } \
634 } while (0)
635
661#define STOP_TIMER_AND_LOG_EVERY(log_level, interval_ns, threshold_ns, timer_name, msg_fmt, ...) \
662 do { \
663 double _elapsed_ns = STOP_TIMER(timer_name, ##__VA_ARGS__); \
664 if (_elapsed_ns >= 0.0 && (threshold_ns == 0 || _elapsed_ns >= (double)(threshold_ns))) { \
665 static atomic_t _log_every_last_time = {0}; \
666 uint64_t _log_every_now = time_get_ns(); \
667 uint64_t _log_every_last = atomic_load_u64(&_log_every_last_time); \
668 if (_log_every_now - _log_every_last >= (uint64_t)(interval_ns)) { \
669 if (atomic_cas_u64(&_log_every_last_time, &_log_every_last, _log_every_now)) { \
670 char _duration_str[TIME_DURATION_BUFFER_SIZE]; \
671 time_pretty((uint64_t)_elapsed_ns, -1, _duration_str, sizeof(_duration_str)); \
672 log_##log_level(msg_fmt " in %s", ##__VA_ARGS__, _duration_str); \
673 } \
674 } \
675 } \
676 } while (0)
677
678// ============================================================================
679// Adaptive Sleep System
680// ============================================================================
681
698
712
725
765uint64_t adaptive_sleep_calculate(adaptive_sleep_state_t *state, size_t queue_depth, size_t target_depth);
766
778void adaptive_sleep_do(adaptive_sleep_state_t *state, size_t queue_depth, size_t target_depth);
779
780/* ============================================================================
781 * Time Format Validation and Formatting
782 * ============================================================================ */
783
808bool time_format_is_valid_strftime(const char *format_str);
809
834int time_format_now(const char *format_str, char *buf, size_t buf_size);
835
865asciichat_error_t time_format_safe(const char *format_str, char *buf, size_t buf_size);
866
868
869/* ============================================================================
870 * Conversion Functions
871 * ============================================================================ */
872
881uint64_t time_timespec_to_ns(const struct timespec *ts);
882
Synchronized per-thread pending error stacks and value snapshots. SET_ERRNO pushes,...
int buffer_size
Size of circular buffer.
Definition grep.c:68
unsigned long long uint64_t
Definition common.h:63
asciichat_error_t
Error and exit codes - unified status values (0-255).
Definition error_codes.h:44
double timer_stop(const char *name)
Stop a named timer and return elapsed time.
Definition time.c:255
int time_pretty_now(int decimals, char *buffer, size_t buffer_size)
Format current monotonic time as pretty duration.
Definition time.c:476
bool timer_start(const char *name)
Start a named timer.
Definition time.c:204
bool time_format_is_valid_strftime(const char *format_str)
Validate strftime format string against known safe specifiers.
Definition time.c:647
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 time.c:566
int time_pretty(uint64_t nanoseconds, int decimals, char *buffer, size_t buffer_size)
Format nanoseconds as a compact duration with configurable sub-minute precision.
Definition time.c:374
int time_format_now(const char *format_str, char *buf, size_t buf_size)
Format current time using strftime format string.
Definition time.c:722
uint64_t time_timespec_to_ns(const struct timespec *ts)
Convert struct timespec to nanoseconds.
Definition time.c:137
void timer_system_destroy(void)
Cleanup the timing system.
Definition time.c:177
#define NS_PER_MS_INT
Definition time.h:168
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 time.c:485
void adaptive_sleep_init(adaptive_sleep_state_t *state, const adaptive_sleep_config_t *config)
Initialize adaptive sleep state with configuration.
Definition time.c:545
int time_human_readable(int64_t nanoseconds, char *buffer, size_t buffer_size)
Format nanoseconds as human-readable relative duration (moment.js style).
Definition time.c:508
uint64_t time_elapsed_ns(uint64_t start_ns, uint64_t end_ns)
Calculate elapsed time with wraparound safety.
Definition time.c:123
#define NS_PER_US_INT
Definition time.h:167
int format_uptime_hms(int hours, int minutes, int seconds, char *buffer, size_t buffer_size)
Format uptime as HH:MM:SS string.
Definition time.c:318
void time_sleep_ns(uint64_t ns)
Configuration for adaptive sleep behavior.
Definition time.c:113
bool timer_is_initialized(void)
Check if timing system is initialized.
Definition time.c:310
bool timer_system_init(void)
Initialize the timing system.
Definition time.c:155
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 time.c:629
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 time.c:758
int time_human_readable_now(char *buffer, size_t buffer_size)
Format current monotonic time as human-readable relative duration.
Definition time.c:536
Configuration for adaptive sleep behavior.
Definition time.h:691
double min_speed_multiplier
Minimum speed (max sleep) - usually 1.0 (baseline speed).
Definition time.h:693
double max_speed_multiplier
Maximum speed (min sleep) - e.g., 4.0 = process 4x faster.
Definition time.h:694
uint64_t baseline_sleep_ns
Normal sleep time in nanoseconds (when queue is at target).
Definition time.h:692
double speedup_rate
Ramp-up rate when queue builds (0.0-1.0, higher = faster ramp).
Definition time.h:695
double slowdown_rate
Ramp-down rate when queue empties (0.0-1.0, higher = faster ramp).
Definition time.h:696
Runtime state for adaptive sleep.
Definition time.h:707
double current_speed_multiplier
Current speed state (1.0 = baseline, >1.0 = faster).
Definition time.h:709
uint64_t last_sleep_ns
Last calculated sleep time (for debugging).
Definition time.h:710
adaptive_sleep_config_t config
Configuration (copied, not referenced).
Definition time.h:708
Individual timer record for a named timing operation.
Definition time.h:260
uint64_t start_ticks
Start time in sokol ticks.
Definition time.h:262
char * name
Timer name (heap-allocated, unique key).
Definition time.h:261
UT_hash_handle hh
uthash handle (makes this hashable by name)
Definition time.h:263
⏱️ High-precision timing utilities using sokol_time.h and uthash