diff options
author | Mitya Selivanov <automainint@guattari.tech> | 2024-07-14 21:12:37 +0200 |
---|---|---|
committer | Mitya Selivanov <automainint@guattari.tech> | 2024-07-14 21:12:37 +0200 |
commit | 30740ca4131d1f574718262451b4410207dc8d4e (patch) | |
tree | fc88b16a216079397ad85b9c6b1a1c1c5712a814 /kit/async_function.h | |
parent | 5e3c99bb1cf1d03ea006300121265571f5008fd2 (diff) | |
download | saw-30740ca4131d1f574718262451b4410207dc8d4e.zip |
Reworking the build system
Diffstat (limited to 'kit/async_function.h')
-rw-r--r-- | kit/async_function.h | 241 |
1 files changed, 241 insertions, 0 deletions
diff --git a/kit/async_function.h b/kit/async_function.h new file mode 100644 index 0000000..5460fd6 --- /dev/null +++ b/kit/async_function.h @@ -0,0 +1,241 @@ +#ifndef KIT_ASYNC_FUNCTION_H +#define KIT_ASYNC_FUNCTION_H + +#include "types.h" + +#include <string.h> + +#ifdef __GNUC__ +#define KIT_FALLTHROUGH __attribute__((fallthrough)); +#else +#define KIT_FALLTHROUGH +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct { + i32 _; +} kit_af_void; + +typedef void (*kit_af_state_machine)(void *self_void_); + +#define KIT_AF_STATE_DATA \ + struct { \ + i32 _index; \ + i32 _id; \ + kit_af_state_machine _state_machine; \ + } + +typedef struct { + KIT_AF_STATE_DATA; +} kit_af_type_void; + +#if defined(__GNUC__) || defined(__clang__) +# pragma GCC diagnostic push +# pragma GCC diagnostic ignored "-Wunused-function" +# pragma GCC diagnostic ignored "-Wunknown-pragmas" +#endif + +#define KIT_AF_INTERNAL(coro_) (*((kit_af_type_void *) (coro_))) + +#ifdef KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH +// Application should implement this function if custom async +// function dispatch is enabled. +// +// See KIT_ENABLE_CUSTOM_ASYNC_FUNCTION_DISPATCH macro. +// +void kit_async_function_dispatch(void *promise); +#else +static void kit_async_function_dispatch(void *promise) { + // Dynamic dispatch by default. + // + KIT_AF_INTERNAL(promise)._state_machine(promise); +} +#endif + +#if defined(__GNUC__) || defined(__clang__) +# pragma GCC diagnostic pop +#endif + +#define KIT_AF_STATE(ret_type_, name_, ...) \ + struct name_##_coro_state_ { \ + KIT_AF_STATE_DATA; \ + ret_type_ return_value; \ + __VA_ARGS__ \ + } + +#define KIT_AF_DECL(name_) void name_(void *self_void_) + +#define KIT_CORO_IMPL(name_) \ + KIT_AF_DECL(name_) { \ + struct name_##_coro_state_ *self = \ + (struct name_##_coro_state_ *) self_void_; \ + switch (self->_index) { \ + case 0:; + +#define KIT_AF_LINE_() __LINE__ + +#define KIT_CORO_END \ + } \ + self->_index = -1; \ + } + +#define KIT_CORO_DECL(ret_type_, name_, ...) \ + KIT_AF_STATE(ret_type_, name_, __VA_ARGS__); \ + KIT_AF_DECL(name_) + +#define KIT_CORO(ret_type_, name_, ...) \ + KIT_AF_STATE(ret_type_, name_, __VA_ARGS__); \ + KIT_CORO_IMPL(name_) + +#define KIT_CORO_DECL_VOID(name_, ...) \ + KIT_CORO_DECL(kit_af_void, name_, __VA_ARGS__) + +#define KIT_CORO_VOID(name_, ...) \ + KIT_CORO(kit_af_void, name_, __VA_ARGS__) + +#define KIT_STATIC_CORO(ret_type_, name_, ...) \ + KIT_AF_STATE(ret_type_, name_, __VA_ARGS__); \ + static KIT_CORO_IMPL(name_) + +#define KIT_STATIC_CORO_VOID(name_, ...) \ + KIT_STATIC_CORO(kit_af_void, name_, __VA_ARGS__) + +#define KIT_AF_EXECUTE(promise_) \ + kit_async_function_dispatch(&(promise_)) + +#define KIT_AF_NEXT(promise_) \ + (kit_async_function_dispatch(&(promise_)), (promise_).return_value) + +#define KIT_AF_YIELD(...) \ + do { \ + self->_index = KIT_AF_LINE_(); \ + self->return_value = __VA_ARGS__; \ + return; \ + case KIT_AF_LINE_():; \ + } while (0) + +#define KIT_AF_YIELD_VOID \ + do { \ + self->_index = KIT_AF_LINE_(); \ + return; \ + case KIT_AF_LINE_():; \ + } while (0) + +#define KIT_AF_RETURN(...) \ + do { \ + self->_index = -1; \ + self->return_value = __VA_ARGS__; \ + return; \ + } while (0) + +#define KIT_AF_RETURN_VOID \ + do { \ + self->_index = -1; \ + return; \ + } while (0) + +#define KIT_AF_AWAIT(promise_) \ + do { \ + KIT_FALLTHROUGH \ + case KIT_AF_LINE_(): \ + if ((promise_)._index != -1) { \ + self->_index = KIT_AF_LINE_(); \ + kit_async_function_dispatch(&(promise_)); \ + } \ + if ((promise_)._index != -1) \ + return; \ + } while (0) + +#define KIT_AF_YIELD_AWAIT(promise_) \ + do { \ + KIT_FALLTHROUGH \ + case KIT_AF_LINE_(): \ + if ((promise_)._index != -1) { \ + self->_index = KIT_AF_LINE_(); \ + kit_async_function_dispatch(&(promise_)); \ + self->return_value = (promise_).return_value; \ + return; \ + } \ + } while (0) + +#define KIT_AF_TYPE(coro_) struct coro_##_coro_state_ + +#define KIT_AF_INITIAL(id_, coro_) \ + ._index = 0, ._id = (id_), ._state_machine = (coro_) + +#define KIT_AF_CREATE(promise_, coro_, ...) \ + KIT_AF_TYPE(coro_) \ + promise_ = { KIT_AF_INITIAL(0, coro_), __VA_ARGS__ } + +#define KIT_AF_CREATE_ID(promise_, id_, ...) \ + KIT_AF_TYPE(coro_) \ + promise_ = { KIT_AF_INITIAL(id_, NULL), __VA_ARGS__ } + +#define KIT_AF_INIT(promise_, coro_, ...) \ + do { \ + KIT_AF_CREATE(kit_af_temp_, coro_, __VA_ARGS__); \ + memcpy(&(promise_), &kit_af_temp_, sizeof kit_af_temp_); \ + } while (0) + +#define KIT_AF_INIT_ID(promise_, id_, ...) \ + do { \ + KIT_AF_CREATE_ID(kit_af_temp_, id_, __VA_ARGS__); \ + memcpy(&(promise_), &kit_af_temp_, sizeof kit_af_temp_); \ + } while (0) + +#define KIT_AF_FINISHED(promise_) ((promise_)._index == -1) + +#define KIT_AF_FINISHED_N(return_, promises_, size_) \ + do { \ + i32 kit_af_index_; \ + (return_) = 1; \ + for (kit_af_index_ = 0; kit_af_index_ < (size_); \ + kit_af_index_++) \ + if (!KIT_AF_FINISHED((promises_)[kit_af_index_])) { \ + (return_) = 0; \ + break; \ + } \ + } while (0) + +#define KIT_AF_FINISHED_ALL(return_, promises_) \ + KIT_AF_FINISHED_N((return_), (promises_), \ + sizeof(promises_) / sizeof((promises_)[0])) + +#ifdef __cplusplus +} +#endif + +#define af_void kit_af_void +#define af_state_machine kit_af_state_machine +#define af_type_void kit_af_type_void +#define AF_STATE_DATA KIT_AF_STATE_DATA +#define AF_STATE KIT_AF_STATE +#define AF_DECL KIT_AF_DECL +#define CORO_IMPL KIT_CORO_IMPL +#define CORO_END KIT_CORO_END +#define CORO_DECL KIT_CORO_DECL +#define CORO KIT_CORO +#define CORO_DECL_VOID KIT_CORO_DECL_VOID +#define STATIC_CORO KIT_STATIC_CORO +#define STATIC_CORO_VOID KIT_STATIC_CORO_VOID +#define CORO_VOID KIT_CORO_VOID +#define AF_EXECUTE KIT_AF_EXECUTE +#define AF_NEXT KIT_AF_NEXT +#define AF_YIELD KIT_AF_YIELD +#define AF_YIELD_VOID KIT_AF_YIELD_VOID +#define AF_RETURN KIT_AF_RETURN +#define AF_RETURN_VOID KIT_AF_RETURN_VOID +#define AF_AWAIT KIT_AF_AWAIT +#define AF_YIELD_AWAIT KIT_AF_YIELD_AWAIT +#define AF_TYPE KIT_AF_TYPE +#define AF_INITIAL KIT_AF_INITIAL +#define AF_CREATE KIT_AF_CREATE +#define AF_INIT KIT_AF_INIT +#define AF_FINISHED KIT_AF_FINISHED +#define AF_FINISHED_N KIT_AF_FINISHED_N +#define AF_FINISHED_ALL KIT_AF_FINISHED_ALL + +#endif |