From bbc7e145157f3d81f3b9e2af3b0f75c08f57d758 Mon Sep 17 00:00:00 2001 From: Antonio Gelain Date: Mon, 2 Oct 2023 16:23:49 +0200 Subject: [PATCH] feat(error-utils): add flags to avoid data races problems --- error-utils/error_utils.c | 37 +++++++++++++++++++++++++++++-------- error-utils/error_utils.h | 4 +++- 2 files changed, 32 insertions(+), 9 deletions(-) diff --git a/error-utils/error_utils.c b/error-utils/error_utils.c index 25af0d4..a66934d 100644 --- a/error-utils/error_utils.c +++ b/error-utils/error_utils.c @@ -311,6 +311,9 @@ void error_utils_init( handler->get_timeout = get_timeout; handler->set_expire = set_expire; + handler->is_expire_invalidated = false; + handler->is_expired_on_invalidation = false; + // Init error instances for (size_t i = 0; i < handler->buffer_size; i++) { handler->errors[i].error = ERROR_UTILS_INVALID_INT; @@ -319,7 +322,6 @@ void error_utils_init( handler->errors[i].is_running = false; handler->errors[i].heap_id = ERROR_UTILS_INVALID_INT; handler->errors[i].timestamp = 0; - handler->errors[i].is_dead = false; handler->errors[i].string_instance = false; handler->expiring[i] = NULL; @@ -365,11 +367,13 @@ bool error_utils_set( err->is_expired = false; err->is_running = true; err->timestamp = handler->get_timestamp(); - err->is_dead = false; // Update handler ++(handler->running); + // Invalidate expire + handler->is_expire_invalidated = true; + // Update heap _error_utils_heap_insert(handler, err); @@ -377,6 +381,13 @@ bool error_utils_set( if (handler->set_expire != NULL && _error_utils_heap_min(handler) == err) handler->set_expire(err->timestamp, handler->get_timeout(error)); + // Resume expire function + handler->is_expire_invalidated = false; + if (handler->is_expired_on_invalidation) { + handler->is_expired_on_invalidation = false; + error_utils_expire_errors(handler); + } + return true; } bool error_utils_reset( @@ -409,8 +420,8 @@ bool error_utils_reset( if (off == handler->buffer_size) return true; - // Set the dead bit of the error - err->is_dead = true; + // Invalidate expire + handler->is_expire_invalidated = true; ErrorUtilsRunningInstance * min = _error_utils_heap_min(handler); @@ -418,12 +429,21 @@ bool error_utils_reset( _error_utils_heap_remove(handler, err); // Update error expire handler if the removed error will be the first to expire - if (handler->set_expire != NULL && handler->expiring[0] != min) + if (handler->set_expire != NULL && handler->expiring[0] != min) { handler->set_expire((handler->expiring[0])->timestamp, handler->get_timeout((handler->expiring[0])->error)); + handler->is_expired_on_invalidation = false; + } // Update handler --(handler->running); + // Resume expire function + handler->is_expire_invalidated = false; + if (handler->is_expired_on_invalidation) { + handler->is_expired_on_invalidation = false; + error_utils_expire_errors(handler); + } + // Update error err->error = ERROR_UTILS_INVALID_INT; err->instance.i = ERROR_UTILS_INVALID_INT; @@ -431,7 +451,6 @@ bool error_utils_reset( err->is_running = false; err->heap_id = ERROR_UTILS_INVALID_INT; err->timestamp = 0; - err->is_dead = 0; return true; } @@ -439,11 +458,13 @@ bool error_utils_reset( void error_utils_expire_errors(ErrorUtilsHandler * handler) { if (handler == NULL) return; + if (handler->is_expire_invalidated) { + handler->is_expired_on_invalidation = true; + return; + } // Get expired error ErrorUtilsRunningInstance * err = _error_utils_heap_min(handler); - if (err->is_dead) - return; // Remove error from heap _error_utils_heap_remove(handler, err); diff --git a/error-utils/error_utils.h b/error-utils/error_utils.h index 4a27def..36cc96d 100644 --- a/error-utils/error_utils.h +++ b/error-utils/error_utils.h @@ -143,7 +143,6 @@ typedef struct { size_t heap_id; bool is_expired : 1; bool is_running : 1; - bool is_dead : 1; // If set to 1 the error cannot expire until it is reset to 0 bool string_instance : 1; // If true the instance is a string, otherwise it is an integer } ErrorUtilsRunningInstance; @@ -161,6 +160,9 @@ typedef struct { ErrorUtilsTimestampCallback get_timestamp; ErrorUtilsTimeoutCallback get_timeout; ErrorUtilsExpireUpdateCallback set_expire; + + bool is_expire_invalidated : 1; // Flag that invalidate the next function call to the expire callback + bool is_expired_on_invalidation : 1; // Flag set to true when the expire callback is called } ErrorUtilsHandler;