You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@celix.apache.org by pn...@apache.org on 2023/05/02 09:59:08 UTC
[celix] 03/04: Add tss abstraction to celix threads
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 <pe...@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);
+}