From 8d16360016e0d8c78dcf30a23c7ac8e9a31be816 Mon Sep 17 00:00:00 2001 From: Joseph <119084558+DerjenigeUberMensch@users.noreply.github.com> Date: Thu, 5 Dec 2024 21:57:37 +0000 Subject: [PATCH] Added TPromise Library (#487) --- tools/TPromises/tpromise.c | 106 +++++++++++++++++++++++++++++++++++++ tools/TPromises/tpromise.h | 101 +++++++++++++++++++++++++++++++++++ 2 files changed, 207 insertions(+) create mode 100644 tools/TPromises/tpromise.c create mode 100644 tools/TPromises/tpromise.h diff --git a/tools/TPromises/tpromise.c b/tools/TPromises/tpromise.c new file mode 100644 index 0000000..fc8320a --- /dev/null +++ b/tools/TPromises/tpromise.c @@ -0,0 +1,106 @@ +#include +#include + +#include "tpromise.h" + + +void * +AwaitTPromise( + TPromise *promise + ) +{ + pthread_mutex_lock(&promise->mutex); + while(!promise->resolved) + { pthread_cond_wait(&promise->cond, &promise->mutex); + } + pthread_mutex_unlock(&promise->mutex); + return promise->data; +} + +void +DestroyTPromise( + TPromise *promise + ) +{ + if(!promise) + { return; + } + + pthread_mutex_destroy(&promise->mutex); + pthread_cond_destroy(&promise->cond); + + free(promise); +} + +int +IsTPromiseDone( + TPromise *promise + ) +{ + int promise_done = 0; + + if(!promise) + { return promise_done; + } + + pthread_mutex_lock(&promise->mutex); + if(promise->resolved) + { promise_done = 1; + } + pthread_mutex_unlock(&promise->mutex); + + return promise_done; +} + +TPromise * +NewTPromise( + void + ) +{ + TPromise *promise = malloc(sizeof(*promise)); + if(promise) + { + int status = NewTPromiseFilled(promise); + if(status != EXIT_SUCCESS) + { + free(promise); + promise = NULL; + } + } + return promise; +} + +int +NewTPromiseFilled( + TPromise *promise_return + ) +{ + if(!promise_return) + { return EXIT_FAILURE; + } + const TPromise _cpy = + { + .data = NULL, + .resolved = 0, + .mutex = PTHREAD_MUTEX_INITIALIZER, + .cond = PTHREAD_COND_INITIALIZER, + }; + *promise_return = _cpy; + return EXIT_SUCCESS; +} + +void +ResolveTPromise( + TPromise *promise, + void *data + ) +{ + pthread_mutex_lock(&promise->mutex); + if(!promise->resolved) + { + promise->data = data; + promise->resolved = 1; + } + pthread_cond_signal(&promise->cond); + pthread_mutex_unlock(&promise->mutex); +} diff --git a/tools/TPromises/tpromise.h b/tools/TPromises/tpromise.h new file mode 100644 index 0000000..596e6a4 --- /dev/null +++ b/tools/TPromises/tpromise.h @@ -0,0 +1,101 @@ +#ifndef __THREAD__PROMISE__H__ +#define __THREAD__PROMISE__H__ + +#ifdef __cplusplus +extern "C" { +#endif + +#include + +typedef struct TPromise TPromise; + +struct +TPromise +{ + void *data; + int resolved; + /* 4bytes pad */ + + pthread_mutex_t mutex; + pthread_cond_t cond; +}; + +/* (A)Waits for a promise to resolve. + * + * NOTE: NULL may be returned if ResolveTPromise() was specified as NULL data. + * NOTE: Awaiting a promise multiple times will not yield different results. + * NOTE: Attempting to await a destroyed promise is undefined. + * + * RETURN: Data from Promise. + */ +void * +AwaitTPromise( + TPromise *promise + ); + + +/* Destroys the given promise, usage of promise after being destroyed is undefined. + * + * NOTE: if a promise is being resolved or awaited, behaviour is undefined. + * + */ +void +DestroyTPromise( + TPromise *promise + ); + +/* Returns wheter or not promise has resolved its data. + * + * RETURN: true on is Done. + * RETURN: false otherwise. + */ +int +IsTPromiseDone( + TPromise *promise + ); + +/* Allocates and intializes a promise for use. + * + * NOTE: This is the only Failure point for TPromises. + * + * RETURN: TPromise * on Success. + * RETURN: NULL on Failure. + */ +TPromise * +NewTPromise( + void + ); + +/* Intializes a promise for use. + * + * NOTE: This is the only Failure point for TPromises. + * NOTE: field 'promise_return' SHOULD be allocated memory, at the minimum static stack memory. + * This is to avoid deadlocks in threads. + * + * RETURN: EXIT_SUCCESS on Success. + * RETURN: EXIT_FAILURE on Failure. + */ +int +NewTPromiseFilled( + TPromise *promise_return + ); + +/* Resolves a TPromise by updating its data. + * + * NOTE: field 'data' MAY be NULL, in such cases NULL will be set as data. + * NOTE: A promise may only be resolved once, further attempts to resolve a promise, + * Will simply 'wakeup' the other process/thread awaiting for the response. + * NOTE: Attempting to resolve a destroyed promise is undefined. + */ +void +ResolveTPromise( + TPromise *promise, + void *data + ); + + +#ifdef __cplusplus +} +#endif + +#endif