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);
+}

Reply via email to