bio
 
Loading...
Searching...
No Matches
bio.h
1#ifndef BIO_MAIN_H
2#define BIO_MAIN_H
3
4#include <stdint.h>
5#include <stddef.h>
6#include <stdarg.h>
7#include <stdbool.h>
8
9#ifndef DOXYGEN
10
11#if defined(__GNUC__) || defined(__clang__)
12# define BIO_FORMAT_ATTRIBUTE(FMT, VA) __attribute__((format(printf, FMT, VA)))
13# define BIO_FORMAT_CHECK(...) (void)(sizeof(0))
14#else
15# include <stdio.h>
16# define BIO_FORMAT_ATTRIBUTE(FMT, VA)
17# define BIO_FORMAT_CHECK(...) (void)(sizeof(printf(__VA_ARGS__)))
18#endif
19
20#endif
21
38#define BIO_LOG(LEVEL, ...) \
39 (BIO_FORMAT_CHECK(__VA_ARGS__), bio_log(LEVEL, __FILE__, __LINE__, __VA_ARGS__))
40
42#define BIO_TRACE(...) BIO_LOG(BIO_LOG_LEVEL_TRACE, __VA_ARGS__)
43
45#define BIO_DEBUG(...) BIO_LOG(BIO_LOG_LEVEL_DEBUG, __VA_ARGS__)
46
48#define BIO_INFO(...) BIO_LOG(BIO_LOG_LEVEL_INFO , __VA_ARGS__)
49
51#define BIO_WARN(...) BIO_LOG(BIO_LOG_LEVEL_WARN , __VA_ARGS__)
52
54#define BIO_ERROR(...) BIO_LOG(BIO_LOG_LEVEL_ERROR, __VA_ARGS__)
55
57#define BIO_FATAL(...) BIO_LOG(BIO_LOG_LEVEL_FATAL, __VA_ARGS__)
58
73#define BIO_ERROR_FMT "%s (%s[%d]) (from %s:%d)"
74
80#define BIO_ERROR_FMT_ARGS(error) \
81 (bio_has_error((error)) ? bio_strerror((error)) : "No error"), \
82 (bio_has_error((error)) ? (error)->tag->name : "bio.error.core"), \
83 ((error)->code), \
84 ((error)->file ? (error)->file : "<no source info>"), \
85 ((error)->line)
86
95#define BIO_TAG_INIT(NAME) \
96 { \
97 .name = NAME, \
98 .file = __FILE__, \
99 .line = __LINE__, \
100 }
101
112#define BIO_INVALID_HANDLE ((bio_handle_t){ .index = 0 })
113
120typedef void (*bio_entrypoint_t)(void* userdata);
121
126typedef struct {
127 int32_t index;
128 int32_t gen;
130
137typedef struct {
138 bio_handle_t handle;
139} bio_coro_t;
140
147typedef struct {
148 bio_handle_t handle;
150
157typedef struct {
158 bio_handle_t handle;
160
167typedef struct {
168 bio_handle_t handle;
170
189typedef struct {
196 const char* name;
197
199 const char* file;
200
202 int line;
203} bio_tag_t;
204
213typedef int64_t bio_time_t;
214
221typedef struct {
223 struct {
233 unsigned int queue_size;
234 } io_uring;
236
243typedef struct {
245 struct {
256 unsigned int batch_size;
257 } iocp;
259
266typedef struct {
268 struct {
279 unsigned int batch_size;
280 } kqueue;
282
288typedef struct {
290 void* ctx;
291
308 void* (*realloc)(void* ptr, size_t size, void* ctx);
310
317typedef struct {
318 size_t size;
319 void (*init)(void* data);
320 void (*cleanup)(void* data);
321} bio_cls_t;
322
364typedef struct {
368 const char* current_filename;
369
378
461
468typedef struct {
473
479 const char* (*strerror)(int code);
480
490 int code;
491
493 const char* file;
494
496 int line;
498
514
526
535typedef struct {
548 bool daemon;
549
561
574
581typedef struct {
587 int line;
589 const char* file;
591
609typedef void (*bio_log_fn_t)(void* userdata, const bio_log_ctx_t* ctx, const char* msg);
610
624
632extern const bio_tag_t BIO_CORE_ERROR;
633
647void
648bio_init(const bio_options_t* options);
649
651void
653
665void
667
675bool
677
712 bio_entrypoint_t entrypoint,
713 void* userdata,
714 const bio_coro_options_t* options
715);
716
730static inline bio_coro_t
731bio_spawn(bio_entrypoint_t entrypoint, void* userdata) {
732 return bio_spawn_ex(entrypoint, userdata, NULL);
733}
734
738
742
753void
755
797
808bool
810
823void
825
832bool
834
868void
870 bio_signal_t* signals,
871 int num_signals,
872 bool wait_all
873);
874
880static inline void
882 bio_wait_for_signals(&signal, 1, true);
883}
884
924
936void
938
946static inline void
948 bio_signal_t term_signal = bio_make_signal();
949 bio_monitor(coro, term_signal);
950 bio_wait_for_one_signal(term_signal);
951}
952
980void
981bio_set_coro_data(void* data, const bio_tag_t* tag);
982
1005void*
1007
1019void
1020bio_set_coro_name(const char* name);
1021
1029const char*
1031
1061void*
1063
1129bio_make_handle(void* obj, const bio_tag_t* tag);
1130
1155void*
1157
1169void*
1171
1177const bio_tag_t*
1179
1181static inline int
1183 if (lhs.index != rhs.index) {
1184 return lhs.index - rhs.index;
1185 } else {
1186 return lhs.gen - rhs.gen;
1187 }
1188}
1189
1216BIO_FORMAT_ATTRIBUTE(4, 5)
1217void
1219 bio_log_level_t level,
1220 const char* file,
1221 int line,
1222 const char* fmt,
1223 ...
1224);
1225
1241bio_add_logger(bio_log_level_t min_level, bio_log_fn_t log_fn, void* userdata);
1242
1249void
1251
1253void
1255
1280static inline bool
1282 return error != NULL && error->tag != NULL;
1283}
1284
1299static inline const char*
1301 if (error != NULL && error->tag != NULL) {
1302 return error->strerror(error->code);
1303 } else {
1304 return NULL;
1305 }
1306}
1307
1309static inline void
1311 if (error != NULL) { error->tag = NULL; }
1312}
1313
1350void
1351bio_run_async(bio_entrypoint_t task, void* userdata, bio_signal_t signal);
1352
1354static inline void
1356 bio_signal_t signal = bio_make_signal();
1357 bio_run_async(task, userdata, signal);
1359}
1360
1370
1392
1395#endif
void(* bio_entrypoint_t)(void *userdata)
Entrypoint for a coroutine.
Definition bio.h:120
bio_coro_t bio_spawn_ex(bio_entrypoint_t entrypoint, void *userdata, const bio_coro_options_t *options)
Spawn a new coroutine.
void * bio_get_cls(const bio_cls_t *cls)
Get a coroutine-local storage (CLS) object.
const char * bio_get_coro_name(bio_coro_t coro)
Get a human-readable name for the coroutine if it has one.
void bio_yield(void)
Let a different coroutine run.
void * bio_get_coro_data(bio_coro_t coro, const bio_tag_t *tag)
Retrieve the data associated with a coroutine.
void bio_set_coro_data(void *data, const bio_tag_t *tag)
Associate the calling coroutine with arbitrary data and a tag.
bio_coro_state_t
State of a coroutine.
Definition bio.h:504
void bio_set_coro_name(const char *name)
Give a human-readable name to the calling coroutine.
static bio_coro_t bio_spawn(bio_entrypoint_t entrypoint, void *userdata)
Spawn a new coroutine.
Definition bio.h:731
bio_coro_t bio_current_coro(void)
Get the handle of the currently running coroutine.
bio_coro_state_t bio_coro_state(bio_coro_t coro)
Check the state of a coroutine.
@ BIO_CORO_DEAD
The coroutine has terminated.
Definition bio.h:512
@ BIO_CORO_RUNNING
The coroutine is the currently running coroutine that called bio_coro_state.
Definition bio.h:508
@ BIO_CORO_WAITING
The coroutine is waiting for a signal.
Definition bio.h:510
@ BIO_CORO_READY
The coroutine is ready to run but not running yet.
Definition bio.h:506
static void bio_clear_error(bio_error_t *error)
Convenient function to clear an error object.
Definition bio.h:1310
static bool bio_has_error(bio_error_t *error)
Convenient function to check whether an error was encountered.
Definition bio.h:1281
const bio_tag_t BIO_CORE_ERROR
A tag for core errors.
static const char * bio_strerror(bio_error_t *error)
Convenient function to format an error into a string.
Definition bio.h:1300
bio_core_error_code_t
Core error codes.
Definition bio.h:616
@ BIO_ERROR_INVALID_ARGUMENT
An invalid argument was provided.
Definition bio.h:620
@ BIO_ERROR_NOT_SUPPORTED
The operation is not supported.
Definition bio.h:622
@ BIO_NO_ERROR
There is no error.
Definition bio.h:618
void * bio_resolve_handle(bio_handle_t handle, const bio_tag_t *tag)
Resolve a handle, returning the associated pointer.
const bio_tag_t * bio_handle_info(bio_handle_t handle)
Retrieve the associated tag of a handle.
bio_handle_t bio_make_handle(void *obj, const bio_tag_t *tag)
Create a new handle.
static int bio_handle_compare(bio_handle_t lhs, bio_handle_t rhs)
Compare two handles.
Definition bio.h:1182
void * bio_close_handle(bio_handle_t handle, const bio_tag_t *tag)
Close a handle and invalidate it.
void bio_init(const bio_options_t *options)
Initialize the framework.
void bio_loop(void)
Enter the event loop until there is no running coroutines.
void bio_terminate(void)
Cleanup.
bool bio_is_terminating(void)
Check whether the calling coroutine is executing inside bio_terminate.
void bio_set_min_log_level(bio_logger_t logger, bio_log_level_t level)
Change the minimum log level for a given logger.
void bio_remove_logger(bio_logger_t logger)
Remove a previously configured logger.
bio_logger_t bio_add_logger(bio_log_level_t min_level, bio_log_fn_t log_fn, void *userdata)
Add a new logger.
void(* bio_log_fn_t)(void *userdata, const bio_log_ctx_t *ctx, const char *msg)
A log callback.
Definition bio.h:609
void bio_log(bio_log_level_t level, const char *file, int line, const char *fmt,...)
Raw logging function.
bio_log_level_t
Log levels.
Definition bio.h:566
@ BIO_LOG_LEVEL_INFO
Info message.
Definition bio.h:569
@ BIO_LOG_LEVEL_TRACE
Tracing message, for debugging.
Definition bio.h:567
@ BIO_LOG_LEVEL_ERROR
Error but usually recoverable.
Definition bio.h:571
@ BIO_LOG_LEVEL_DEBUG
Debug message.
Definition bio.h:568
@ BIO_LOG_LEVEL_FATAL
Fatal, the program usually terminates after this.
Definition bio.h:572
@ BIO_LOG_LEVEL_WARN
Warning.
Definition bio.h:570
bio_exit_reason_t
Result for bio_wait_for_exit.
Definition bio.h:520
static void bio_run_async_and_wait(bio_entrypoint_t task, void *userdata)
Convenient function to start an async task and wait for it to complete.
Definition bio.h:1355
bio_time_t bio_current_time_ms(void)
Return the current time in milliseconds.
int64_t bio_time_t
A timestamp.
Definition bio.h:213
bio_exit_reason_t bio_wait_for_exit(void)
Wait for an exit signal to be delivered by the OS.
void bio_run_async(bio_entrypoint_t task, void *userdata, bio_signal_t signal)
Run a function in the async thread pool.
@ BIO_EXIT_OS_REQUEST
The OS has requested that the program exits.
Definition bio.h:522
@ BIO_EXIT_TERMINATE
bio_terminate has been called
Definition bio.h:524
void bio_unmonitor(bio_monitor_t monitor)
Discard a monitor.
static void bio_join(bio_coro_t coro)
Convenient function to wait for a coroutine to terminate.
Definition bio.h:947
bio_monitor_t bio_monitor(bio_coro_t coro, bio_signal_t signal)
Monitor a coroutine for termination.
bio_signal_t bio_make_signal(void)
Create a new signal.
void bio_wait_for_signals(bio_signal_t *signals, int num_signals, bool wait_all)
Wait for signals to be raised.
static void bio_wait_for_one_signal(bio_signal_t signal)
Convenient function to wait for a single signal.
Definition bio.h:881
void bio_raise_signal_after(bio_signal_t signal, bio_time_t time_ms)
Raise a signal after a delay.
bool bio_raise_signal(bio_signal_t signal)
Raise a signal.
bool bio_check_signal(bio_signal_t signal)
Check whether a signal has been raised.
Custom memory allocator.
Definition bio.h:288
void * ctx
Allocator context.
Definition bio.h:290
Coroutine-local storage (CLS) specification.
Definition bio.h:317
size_t size
Size of the data.
Definition bio.h:318
Coroutine spawn options.
Definition bio.h:535
bool daemon
Whether this coroutine will be a daemon.
Definition bio.h:548
size_t stack_size
Stack size for the coroutine.
Definition bio.h:559
Handle to a coroutine.
Definition bio.h:137
An error returned from a function.
Definition bio.h:468
const char *(* strerror)(int code)
The error formatting function.
Definition bio.h:479
int code
The error code.
Definition bio.h:490
const bio_tag_t * tag
The unique tag representing the domain that error comes from.
Definition bio.h:472
int line
The line where the error originated from.
Definition bio.h:496
const char * file
The filename where the error originated from.
Definition bio.h:493
Initialization options for FreeBSD.
Definition bio.h:266
unsigned int batch_size
The size of the eventlist that will be passed to kevent
Definition bio.h:279
Definition bio.h:126
int32_t index
For internal use.
Definition bio.h:127
int32_t gen
For internal use.
Definition bio.h:128
Initialization options for Linux.
Definition bio.h:221
unsigned int queue_size
The size of the submission and completion queue.
Definition bio.h:233
Context for a log function.
Definition bio.h:581
bio_coro_t coro
The coroutine calling the log function.
Definition bio.h:583
bio_log_level_t level
The log level.
Definition bio.h:585
const char * file
The source file where the logging call originated from.
Definition bio.h:589
int line
The source line where the logging call originated from.
Definition bio.h:587
Logging options.
Definition bio.h:364
const char * current_filename
Full path to the file that is calling bio_init.
Definition bio.h:368
int current_depth_in_project
The depth of the calling file in your project tree.
Definition bio.h:376
Handle to a logger.
Definition bio.h:167
Handle to a monitor.
Definition bio.h:157
Initialization options.
Definition bio.h:408
bio_log_options_t log_options
Logging options.
Definition bio.h:450
int num_threads
Number of threads in the thread pool.
Definition bio.h:436
bio_allocator_t allocator
Custom allocator. Defaults to stdlib if not provided.
Definition bio.h:410
bio_windows_options_t windows
Windows-specific options, ignored on other platforms.
Definition bio.h:456
bio_linux_options_t linux
Linux-specific options, ignored on other platforms.
Definition bio.h:453
int num_cls_buckets
Number of coroutine-local storage (CLS) hash buckets.
Definition bio.h:423
int queue_size
The length of the message queue for each thread in the async thread poo.
Definition bio.h:446
bio_freebsd_options_t freebsd
FreeBSD-specific options, ignored on other platforms.
Definition bio.h:459
Handle to a signal.
Definition bio.h:147
A unique tag.
Definition bio.h:189
const char * name
A human-readable name for the tag.
Definition bio.h:196
const char * file
The file where the tag was defined.
Definition bio.h:199
int line
The line where the tag was defined.
Definition bio.h:202
Initialization options for Windows.
Definition bio.h:243
unsigned int batch_size
The size of the buffer that will be passed to GetQueuedCompletionStatusEx
Definition bio.h:256