This is an automated email from the ASF dual-hosted git repository. pnoltes pushed a commit to branch feature/celix_err in repository https://gitbox.apache.org/repos/asf/celix.git
commit cef5bb8841f96e16bf0d68ddfd55997bfb20fe41 Author: Pepijn Noltes <pepijnnol...@gmail.com> AuthorDate: Tue May 2 11:47:19 2023 +0200 Add tss abstraction to celix threads --- libs/utils/include/celix_errno.h | 3 +- libs/utils/include/celix_threads.h | 61 +++++++++++++++++++++++++++++++++++++- libs/utils/src/celix_threads.c | 30 ++++++++++++++++++- 3 files changed, 91 insertions(+), 3 deletions(-) diff --git a/libs/utils/include/celix_errno.h b/libs/utils/include/celix_errno.h index 8a3dbf02..7a7a89a2 100644 --- a/libs/utils/include/celix_errno.h +++ b/libs/utils/include/celix_errno.h @@ -58,7 +58,7 @@ extern "C" { * \{ */ -struct celix_status { +struct __attribute__((deprecated("use celix_status_t instead"))) celix_status { int code; char *error; }; @@ -178,6 +178,7 @@ CELIX_UTILS_EXPORT const char* celix_strerror(celix_status_t status); */ #define CELIX_ENOMEM CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,ENOMEM) +#define CELIX_EAGAIN CELIX_ERROR_MAKE(CELIX_FACILITY_CERRNO,EAGAIN) /*! @}*///C error map to celix diff --git a/libs/utils/include/celix_threads.h b/libs/utils/include/celix_threads.h index e74074ab..fba1e246 100644 --- a/libs/utils/include/celix_threads.h +++ b/libs/utils/include/celix_threads.h @@ -46,7 +46,7 @@ typedef void *(*celix_thread_start_t)(void *); static const celix_thread_t celix_thread_default = {0, 0}; CELIX_UTILS_EXPORT celix_status_t -celixThread_create(celix_thread_t *new_thread, celix_thread_attr_t *attr, celix_thread_start_t func, void *data); +celixThread_create(celix_thread_t *new_thread, const celix_thread_attr_t *attr, celix_thread_start_t func, void *data); /** * If supported by the platform sets the name of the thread. @@ -136,6 +136,65 @@ CELIX_UTILS_EXPORT celix_status_t celixThreadCondition_signal(celix_thread_cond_ CELIX_UTILS_EXPORT celix_status_t celixThread_once(celix_thread_once_t *once_control, void (*init_routine)(void)); +//Thread Specific Storage (TSS) Abstraction +typedef pthread_key_t celix_tss_key_t; + +/** + * @brief Create a thread specific storage key visible for all threads. + * + * + * Upon creation, the value NULL shall be associated with + * the new key in all active threads of the process. Upon thread creation, + * the value NULL shall be associated with all defined keys in the new thread + * + * An optional destructor function may be associated with each key value. At thread exit, if a key value has a + * non-NULL destructor pointer, and the thread has a non-NULL value associated with that key, the value of the key is + * set to NULL, and then the function pointed to is called with the previously associated value as its sole argument. + * The order of destructor calls is unspecified if more than one destructor exists for a thread when it exits. + * + * @param key The key to create. + * @param destroyFunction The function to call when the key is destroyed. + * @return CELIX_SUCCESS if the key is created successfully. + * + * @retval CELIX_ENOMEM if there was insufficient memory for the key creation. + * @retval CELIX_EAGAIN if the system lacked the necessary resources to create another thread specific data key. + */ +CELIX_UTILS_EXPORT celix_status_t celix_tss_create(celix_tss_key_t* key, void (*destroyFunction)(void*)); + +/** + * @brief Delete a thread specific storage key previously created by celix_tss_create. + * + * @param key The key to delete. + * @return CELIX_SUCCESS if the key is deleted successfully. + * + * @retval CELIX_ILLEGAL_ARGUMENT if the key is invalid. + * @retval CELIX_ILLEGAL_STATE if the key is otherwise not deleted successfully. + */ +CELIX_UTILS_EXPORT celix_status_t celix_tss_delete(celix_tss_key_t key); + +/** + * @brief Set a thread-specific value for the provide thread specific storage key. + * + * @param key The key to set the value for. + * @param value The thread-specific value to set. + * @return CELIX_SUCCESS if the value is set successfully. + * + * @retval CELIX_ILLEGAL_ARGUMENT if the key is invalid. + * @retval CELIX_ENOMEM if there was insufficient memory to set the value. + * @retval CELIX_ILLEGAL_STATE if the value is not set successfully. + */ +CELIX_UTILS_EXPORT celix_status_t celix_tss_set(celix_tss_key_t key, void* value); + +/** + * @brief Get the thread-specific value for the provided thread specific storage key. + * + * @param key The key to get the value for. + * @return The thread-specific value. + * + * @retval NULL if the key is invalid or there is no thread-specific value set for the key. + */ +CELIX_UTILS_EXPORT void* celix_tss_get(celix_tss_key_t key); + #ifdef __cplusplus } #endif diff --git a/libs/utils/src/celix_threads.c b/libs/utils/src/celix_threads.c index 4ad291d3..31e3a9f0 100644 --- a/libs/utils/src/celix_threads.c +++ b/libs/utils/src/celix_threads.c @@ -32,7 +32,7 @@ #include "celix_utils.h" -celix_status_t celixThread_create(celix_thread_t *new_thread, celix_thread_attr_t *attr, celix_thread_start_t func, void *data) { +celix_status_t celixThread_create(celix_thread_t *new_thread, const celix_thread_attr_t *attr, celix_thread_start_t func, void *data) { celix_status_t status = CELIX_SUCCESS; if (pthread_create(&(*new_thread).thread, attr, func, data) != 0) { @@ -236,3 +236,31 @@ celix_status_t celixThreadRwlockAttr_destroy(celix_thread_rwlockattr_t *attr) { celix_status_t celixThread_once(celix_thread_once_t *once_control, void (*init_routine)(void)) { return pthread_once(once_control, init_routine); } + +celix_status_t celix_tss_create(celix_tss_key_t* key, void (*destroyFunction)(void*)) { + int rc = pthread_key_create(key, destroyFunction); + if (rc == 0) { + return CELIX_SUCCESS; + } + return rc == ENOMEM ? CELIX_ENOMEM : CELIX_ILLEGAL_STATE; +} + +celix_status_t celix_tss_delete(celix_tss_key_t key) { + int rc = pthread_key_delete(key); + if (rc == 0) { + return CELIX_SUCCESS; + } + return rc == EINVAL ? CELIX_ILLEGAL_ARGUMENT : CELIX_ILLEGAL_STATE; +} + +celix_status_t celix_tss_set(celix_tss_key_t key, void* value) { + int rc = pthread_setspecific(key, value); + if (rc == 0) { + return CELIX_SUCCESS; + } + return rc == EINVAL ? CELIX_ILLEGAL_ARGUMENT : CELIX_ILLEGAL_STATE; +} + +void* celix_tss_get(celix_tss_key_t key) { + return pthread_getspecific(key); +}