From f8dcae213d96ed2e0d8184b70838b1ce10ee2a4b Mon Sep 17 00:00:00 2001 From: Francesco Date: Wed, 3 Dec 2025 07:59:49 +0100 Subject: [PATCH] refactor(string): remove thread-specific storage --- string/mystring.c | 105 +++++++++++++++++----------------------------- string/mystring.h | 34 +++++++++++++-- 2 files changed, 69 insertions(+), 70 deletions(-) diff --git a/string/mystring.c b/string/mystring.c index cdd0fd3..dcd224b 100644 --- a/string/mystring.c +++ b/string/mystring.c @@ -8,29 +8,6 @@ #include #include -/* Initialize Thread-Specific Storage */ - -static tss_t buffer_key; -static once_flag buffer_once = ONCE_FLAG_INIT; - -typedef struct { - char *buf; /**< Allocated buffer */ - size_t cap; /**< Buffer's capacity */ -} tl_buffer_s; - -static void buffer_destructor(void *buf) { - tl_buffer_s *tb = (tl_buffer_s *)buf; - if (tb == NULL) { - return; - } - free(tb->buf); - free(tb); -} - -static void buffer_key_init(void) { - tss_create(&buffer_key, buffer_destructor); -} - /* Returns the next power of two of a number */ static size_t next_power_two(size_t len) { if (len == 0) @@ -227,65 +204,59 @@ size_t string_cap(string_s *string) { return cap; } +int string_lock(string_s *string) { + if (string == NULL) { + return -1; + } + + if (mtx_lock(&string->lock) != thrd_success) { + return -1; + } + + return 0; +} + +int string_unlock(string_s *string) { + if (string == NULL) { + return -1; + } + + if (mtx_unlock(&string->lock) != thrd_success) { + return -1; + } + + return 0; +} + char *string_cstr(string_s *string) { if (string == NULL || string->data == NULL) { return NULL; } - call_once(&buffer_once, buffer_key_init); + return string->data; +} + +char *string_copy(string_s *string) { + if (string == NULL || string->data == NULL) { + return NULL; + } if (mtx_lock(&string->lock) != thrd_success) { return NULL; } - size_t need = string->size + 1; - - /* Retrieve thread local buffer */ - tl_buffer_s *tb = (tl_buffer_s *)tss_get(buffer_key); - if (tb == NULL) { - /* Not found, make a new one */ - tb = malloc(sizeof(tl_buffer_s)); - if (tb == NULL) { - mtx_unlock(&string->lock); - - return NULL; - } - - tb->cap = next_power_two(need); - tb->buf = malloc(tb->cap); - if (tb->buf == NULL) { - free(tb); - mtx_unlock(&string->lock); - - return NULL; - } - - if (tss_set(buffer_key, tb) != thrd_success) { - free(tb->buf); - free(tb); - mtx_unlock(&string->lock); - - return NULL; - } - } else if (tb->cap < need) { - /* Found, but we need a bigger buffer */ - size_t newcap = next_power_two(need); - char *tmp = realloc(tb->buf, newcap); - if (tmp == NULL) { - mtx_unlock(&string->lock); - - return NULL; - } - - tb->buf = tmp; - tb->cap = newcap; + char *cpy = malloc(string->size + 1); + if (!cpy) { + mtx_unlock(&string->lock); + return NULL; } - memcpy(tb->buf, string->data, need); + memcpy(cpy, string->data, string->size); + cpy[string->size] = '\0'; mtx_unlock(&string->lock); - return tb->buf; + return cpy; } int string_compare(string_s *s1, string_s *s2) { diff --git a/string/mystring.h b/string/mystring.h index ebff71a..e312abd 100644 --- a/string/mystring.h +++ b/string/mystring.h @@ -77,13 +77,41 @@ size_t string_cap(string_s *string); * @brief Get a pointer to a null-terminated C-string. * * @param string String to read. - * @return Pointer to a thread-local buffer, or NULL on failure. + * @return Pointer to string->data. * - * @note Valid until the next call in the same thread. Do NOT free the returned pointer. - * Do NOT call more than once this function in a print function. + * @note See string_lock(). */ char *string_cstr(string_s *string); +/** + * @brief Create a heap-allocated copy of the string content. + * + * @param string String to copy. + * @return Newly allocated null-terminated buffer, or NULL on failure. + * + * @note The caller is responsible for freeing the returned buffer with free(). + * See string_lock(). + */ +char *string_copy(string_s *string); + +/** + * @brief Lock the string for safe reading or writing. + * + * @param string String to lock. + * @return 0 on success, -1 on failure. + * + * @note Use this before calling string_cstr() if you want a stable pointer. + */ +int string_lock(string_s *string); + +/** + * @brief Unlock a previously locked string. + * + * @param string String to unlock. + * @return 0 on success, -1 on failure. + */ +int string_unlock(string_s *string); + /** * @brief Compare two strings. *