diff options
-rw-r--r-- | thunk.h | 50 |
1 files changed, 50 insertions, 0 deletions
@@ -418,6 +418,56 @@ struct thunk_t { \ static int _THUNK_GEN_PROTO(_name, __VA_ARGS__) + +/* this is the public variant which is split across declare & define */ +/* put the declaration in the .h, the define in the .c, be sure to include the + * .h from the implementing .c - not just the consumers. + */ +#define THUNK_DECLARE(_name, ...) \ + int _THUNK_GEN_PROTO(_name, __VA_ARGS__); \ + typedef struct __thunk_environment_##_name { \ + /* struct for encapsulating the calling environment */ \ + thunk_t __thunk; \ + _THUNK_GEN_STRUCT (__VA_ARGS__); \ + } __thunk_environment_##_name; \ + \ + int __thunk_dispatch_##_name(thunk_t *thunk); \ + thunk_t * _THUNK_GEN_PROTO(__thunk_instantiate_##_name, __VA_ARGS__); + + +#define THUNK_DEFINE(_name, ...) \ + int __thunk_dispatch_##_name(thunk_t *thunk) { \ + /* dispatch thunk from associated environment */ \ + __thunk_environment_##_name *env; \ + int r; \ + \ + /* XXX: the embedded __thunk is always at the start, otherwise \ + * container_of() could be used... */ \ + env = (__thunk_environment_##_name *)thunk; \ + assert(env); \ + \ + r = _THUNK_GEN_DISPATCH(_name, env, __VA_ARGS__); \ + free(env); \ + \ + return r; \ + } \ + \ + thunk_t * _THUNK_GEN_PROTO(__thunk_instantiate_##_name, __VA_ARGS__) { \ + /* allocate and populate environment, return it */ \ + __thunk_environment_##_name *env; \ + \ + env = malloc(sizeof(*env)); \ + assert(env); \ + \ + _THUNK_GEN_INITIALIZE(env, __VA_ARGS__); \ + env->__thunk.dispatch = __thunk_dispatch_##_name; \ + \ + return &env->__thunk; \ + } \ + \ + int _THUNK_GEN_PROTO(_name, __VA_ARGS__) + + /* Call the appropriate instantiate function which returns an embedded thunk_t, * this is how you prepare the thunks established via THUNK_DEFINE(). */ #define _THUNK(_call) \ |