#ifndef POLLABLE_H #define POLLABLE_H typedef void *(*future_poll_func)(void *env, void *data); typedef struct future (*future_then_func)(void *env, void *result); struct future { future_poll_func f; future_then_func then; void *env; }; enum future_err_code { FUTURE_ERR_OK, FUTURE_ERR_MISSING_FUNC }; struct future_err { enum future_err_code code; const char *name; }; void *future_poll(struct future *p, void *data, struct future_err *err); void _future_err_set(struct future_err *err, enum future_err_code code); #if defined(IMP) || defined(POLLABLE_IMP) #include void * future_poll(struct future *p, void *data, struct future_err *err) { void *res = p->f(p->env, data); if ( p->then != NULL ) { if ( res == NULL ) { goto exit_ok; } { struct future new_ftr; new_ftr = p->then(p->env, res); p->f = new_ftr.f; p->env = new_ftr.env; p->then = new_ftr.then; } res = NULL; goto exit_ok; } if ( p->f == NULL ) { _future_err_set(err, FUTURE_ERR_MISSING_FUNC); return NULL; } exit_ok: _future_err_set(err, FUTURE_ERR_OK); return res; } void _future_err_set(struct future_err *err, enum future_err_code code) { if ( err == NULL ) { return ; } err->code = code; switch ( code ) { #define _FUTURE_ERR_SET_CASE(c) case c: err->name = #c; break _FUTURE_ERR_SET_CASE(FUTURE_ERR_OK); _FUTURE_ERR_SET_CASE(FUTURE_ERR_MISSING_FUNC); #undef _FUTURE_ERR_SET_CASE } } #endif /* defined(IMP) || defined(POLLABLE_IMP) */ #endif /* POLLABLE_H */