Add finally callback to promises.
Some checks failed
continuous-integration/drone/push Build is failing

A finally callback is called on success or fail of the promise.
This commit is contained in:
Madeorsk 2023-07-15 19:51:44 +02:00
parent a98502b1bb
commit 2552fa9db9
3 changed files with 42 additions and 0 deletions

View File

@ -14,6 +14,7 @@ typedef struct {
pthread_t thread; pthread_t thread;
ksrarray *then_callbacks; // array of then callbacks. ksrarray *then_callbacks; // array of then callbacks.
ksrarray *catch_callbacks; // array of catch 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. bool successful; // determine if the promise has been fulfilled or not.
void *result; // the promised result. 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); typedef void (*ksrpromise_then_callback_f)(void *result, void *userdata);
// type of catch callback. // type of catch callback.
typedef void (*ksrpromise_catch_callback_f)(int code, const char *message, void *userdata); 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. * Create a new promise.
@ -63,6 +66,7 @@ void* ksrpromise_await(ksrpromise *promise);
* Set a new callback to call on promise resolution. * Set a new callback to call on promise resolution.
* @param promise - the promise for which to set a resolution callback. * @param promise - the promise for which to set a resolution callback.
* @param callback - the callback to set. * @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); 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. * Set a new callback to call on promise rejection.
* @param promise - the promise for which to set a rejection callback. * @param promise - the promise for which to set a rejection callback.
* @param callback - a callback to set. * @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); 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. * Determine if the given promise is successful or not.
* @param - the promise to check. * @param - the promise to check.

View File

@ -40,6 +40,13 @@ typedef struct {
ksrpromise_catch_callback_f callback; ksrpromise_catch_callback_f callback;
void *userdata; void *userdata;
} promise_catch_user_callback; } 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. * The main promise thread function.
@ -62,6 +69,7 @@ ksrpromise* ksrpromise_new(ksrpromise_execution_f exec, void *data)
ksrpromise *promise = malloc(sizeof(ksrpromise)); ksrpromise *promise = malloc(sizeof(ksrpromise));
promise->then_callbacks = ksrarray_new_tiny(); promise->then_callbacks = ksrarray_new_tiny();
promise->catch_callbacks = ksrarray_new_tiny(); promise->catch_callbacks = ksrarray_new_tiny();
promise->finally_callbacks = ksrarray_new_tiny();
promise->successful = false; promise->successful = false;
promise->result = NULL; promise->result = NULL;
promise->error_code = 0; 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). // 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); 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);
}

View File

@ -44,12 +44,20 @@ void on_promise_failed(int error_code, const char *error_message, void *userdata
assert(str_equals("blabla", 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) int main(void)
{ {
// try to create a promise. // try to create a promise.
ksrpromise *promise = ksrpromise_new(promise_execution_ok, NULL); ksrpromise *promise = ksrpromise_new(promise_execution_ok, NULL);
// checking that then is properly launched. // checking that then is properly launched.
ksrpromise_then(promise, on_promise_ok, NULL); 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. // checking that await is working properly on a successful promise.
assert(str_equals("OK", ksrpromise_await(promise))); assert(str_equals("OK", ksrpromise_await(promise)));
@ -57,6 +65,8 @@ int main(void)
ksrpromise *promise_fail = ksrpromise_new(promise_execution_error, "hello"); ksrpromise *promise_fail = ksrpromise_new(promise_execution_error, "hello");
// checking that catch is properly launched. // checking that catch is properly launched.
ksrpromise_catch(promise_fail, on_promise_failed, "blabla"); 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. // checking that await is working properly on a promise which fails.
assert(ksrpromise_await(promise_fail) == NULL); assert(ksrpromise_await(promise_fail) == NULL);