diff --git a/include/evfibers/fiber.h b/include/evfibers/fiber.h index 37880ef..10413c7 100644 --- a/include/evfibers/fiber.h +++ b/include/evfibers/fiber.h @@ -231,6 +231,7 @@ enum fbr_error_code { FBR_EPROTOBUF, FBR_EBUFFERNOSPACE, FBR_EEIO, + FBR_EAGAIN, }; /** @@ -1536,9 +1537,30 @@ void fbr_cond_destroy(FBR_P_ struct fbr_cond_var *cond); * @see fbr_cond_destroy * @see fbr_cond_broadcast * @see fbr_cond_signal + * @see fbr_cond_wait_wto */ int fbr_cond_wait(FBR_P_ struct fbr_cond_var *cond, struct fbr_mutex *mutex); +/** + * Waits until condition is met or specified timeout is reached. + * @returns 0 on success, -1 on error including reaching specified timeout + * + * Current fiber is suspended until a signal send via fbr_cond_signal or + * fbr_cond_broadcast to the corresponding condition variable but not more than + * specified timeout. + * + * A mutex must be acquired by the calling fiber prior to waiting for a + * condition. Internally mutex is released and reacquired again before + * returning. Upon successful return calling fiber will hold the mutex. + * + * In case of timeout FBR_EAGAIN is set as f_errno + * + * @see fbr_cond_wait + */ + +int fbr_cond_wait_wto(FBR_P_ struct fbr_cond_var *cond, struct fbr_mutex *mutex, + ev_tstamp timeout); + /** * Broadcasts a signal to all fibers waiting for condition. * diff --git a/src/fiber.c b/src/fiber.c index 5406d71..76ce2e6 100644 --- a/src/fiber.c +++ b/src/fiber.c @@ -254,6 +254,8 @@ const char *fbr_strerror(_unused_ FBR_P_ enum fbr_error_code code) return "Not enough space in the buffer"; case FBR_EEIO: return "libeio request error"; + case FBR_EAGAIN: + return "Try again"; } return "Unknown error"; } @@ -1733,6 +1735,23 @@ int fbr_cond_wait(FBR_P_ struct fbr_cond_var *cond, struct fbr_mutex *mutex) return_success(0); } +int fbr_cond_wait_wto(FBR_P_ struct fbr_cond_var *cond, struct fbr_mutex *mutex, + ev_tstamp timeout) +{ + struct fbr_ev_cond_var ev; + int retval; + + if (mutex && fbr_id_isnull(mutex->locked_by)) + return_error(-1, FBR_EINVAL); + + fbr_ev_cond_var_init(FBR_A_ &ev, cond, mutex); + retval = fbr_ev_wait_one_wto(FBR_A_ &ev.ev_base, timeout); + if (-1 == retval) + return_error(-1, FBR_EAGAIN); + + return_success(0); +} + void fbr_cond_broadcast(FBR_P_ struct fbr_cond_var *cond) { struct fbr_id_tailq_i *item;