diff --git a/include/ksr/promises.h b/include/ksr/promises.h index 2211fca..7eaf794 100644 --- a/include/ksr/promises.h +++ b/include/ksr/promises.h @@ -14,6 +14,7 @@ typedef struct { pthread_t thread; ksrarray *then_callbacks; // array of then callbacks. ksrarray *catch_callbacks; // array of catch callbacks. + ksrarray *finally_callbacks; // array of finally callbacks. bool successful; // determine if the promise has been fulfilled or not. void *result; // the promised result. @@ -28,6 +29,8 @@ typedef void (*ksrpromise_execution_f)(ksrpromise *promise, void *userdata); typedef void (*ksrpromise_then_callback_f)(void *result, void *userdata); // type of catch callback. typedef void (*ksrpromise_catch_callback_f)(int code, const char *message, void *userdata); +// type of finally callback. +typedef void (*ksrpromise_finally_callback_f)(void *userdata); /** * Create a new promise. @@ -63,6 +66,7 @@ void* ksrpromise_await(ksrpromise *promise); * Set a new callback to call on promise resolution. * @param promise - the promise for which to set a resolution callback. * @param callback - the callback to set. + * @param userdata - custom data to passed to the callback. */ void ksrpromise_then(ksrpromise *promise, ksrpromise_then_callback_f, void *userdata); @@ -70,9 +74,18 @@ void ksrpromise_then(ksrpromise *promise, ksrpromise_then_callback_f, void *user * Set a new callback to call on promise rejection. * @param promise - the promise for which to set a rejection callback. * @param callback - a callback to set. + * @param userdata - custom data to passed to the callback. */ void ksrpromise_catch(ksrpromise *promise, ksrpromise_catch_callback_f, void *userdata); +/** + * Set a new callback to call on promise resolution or rejection. + * @param promise - the promise for which to set a finally callback. + * @param callback - a callback to set. + * @param userdata - custom data to passed to the callback. + */ +void ksrpromise_finally(ksrpromise *promise, ksrpromise_finally_callback_f, void *userdata); + /** * Determine if the given promise is successful or not. * @param - the promise to check. diff --git a/src/promises.c b/src/promises.c index 7a84bf0..b733863 100644 --- a/src/promises.c +++ b/src/promises.c @@ -40,6 +40,13 @@ typedef struct { ksrpromise_catch_callback_f callback; void *userdata; } promise_catch_user_callback; +/** + * Promise finally user callback. + */ +typedef struct { + ksrpromise_finally_callback_f callback; + void *userdata; +} promise_finally_user_callback; /** * The main promise thread function. @@ -62,6 +69,7 @@ ksrpromise* ksrpromise_new(ksrpromise_execution_f exec, void *data) ksrpromise *promise = malloc(sizeof(ksrpromise)); promise->then_callbacks = ksrarray_new_tiny(); promise->catch_callbacks = ksrarray_new_tiny(); + promise->finally_callbacks = ksrarray_new_tiny(); promise->successful = false; promise->result = NULL; promise->error_code = 0; @@ -166,3 +174,14 @@ void ksrpromise_catch(ksrpromise *promise, ksrpromise_catch_callback_f callback, // we use a pointer of the given function pointer as a workaround for generic arrays (see https://stackoverflow.com/a/16682718/7496951). ksrarray_push(promise->catch_callbacks, user_callback); } + +void ksrpromise_finally(ksrpromise *promise, ksrpromise_finally_callback_f callback, void *userdata) +{ + // allocate user callback. + promise_finally_user_callback *user_callback = malloc(sizeof(promise_finally_user_callback)); + user_callback->callback = callback; + user_callback->userdata = userdata; + + // we use a pointer of the given function pointer as a workaround for generic arrays (see https://stackoverflow.com/a/16682718/7496951). + ksrarray_push(promise->finally_callbacks, user_callback); +} diff --git a/tests/ksrpromises.c b/tests/ksrpromises.c index 73e0289..8576d8c 100644 --- a/tests/ksrpromises.c +++ b/tests/ksrpromises.c @@ -44,12 +44,20 @@ void on_promise_failed(int error_code, const char *error_message, void *userdata assert(str_equals("blabla", userdata)); } +void on_promise_finished(void *userdata) +{ + // checking that user data have been properly transfered. + assert(str_equals("test_finally", userdata)); +} + int main(void) { // try to create a promise. ksrpromise *promise = ksrpromise_new(promise_execution_ok, NULL); // checking that then is properly launched. ksrpromise_then(promise, on_promise_ok, NULL); + // checking that finally is properly launched. + ksrpromise_finally(promise, on_promise_finished, "test_finally"); // checking that await is working properly on a successful promise. assert(str_equals("OK", ksrpromise_await(promise))); @@ -57,6 +65,8 @@ int main(void) ksrpromise *promise_fail = ksrpromise_new(promise_execution_error, "hello"); // checking that catch is properly launched. ksrpromise_catch(promise_fail, on_promise_failed, "blabla"); + // checking that finally is properly launched. + ksrpromise_finally(promise, on_promise_finished, "test_finally"); // checking that await is working properly on a promise which fails. assert(ksrpromise_await(promise_fail) == NULL);