From 2704061593ce03e8cd23b6ea6759dbcdc59eeffd Mon Sep 17 00:00:00 2001 From: Kevin Day Date: Sat, 23 Jan 2021 16:59:21 -0600 Subject: [PATCH] Update: add missing thread functionality and fix an initializer. --- level_0/f_thread/c/private-thread.c | 128 ++++++++++++++ level_0/f_thread/c/private-thread.h | 156 +++++++++++++++++ level_0/f_thread/c/thread-common.h | 66 ++++++- level_0/f_thread/c/thread.c | 249 +++++++++++++++++++++++++- level_0/f_thread/c/thread.h | 339 +++++++++++++++++++++++++++++++++++- 5 files changed, 924 insertions(+), 14 deletions(-) diff --git a/level_0/f_thread/c/private-thread.c b/level_0/f_thread/c/private-thread.c index fad975d..da63306 100644 --- a/level_0/f_thread/c/private-thread.c +++ b/level_0/f_thread/c/private-thread.c @@ -66,6 +66,134 @@ extern "C" { } #endif // !defined(_di_f_thread_attributes_decrease_) || !defined(_di_f_thread_attributes_decrease_by_) || !defined(_di_f_thread_attributes_increase_) || !defined(_di_f_thread_attributes_increase_by_) +#if !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) || !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) || !defined(_di_f_thread_condition_attributes_resize_) + f_status_t private_f_thread_condition_attribute_delete(f_thread_condition_attribute_t *attribute) { + + const int error = pthread_condattr_destroy(attribute); + + if (error) { + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) || !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) || !defined(_di_f_thread_condition_attributes_resize_) + +#if !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) + f_status_t private_f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < attributes->size; ++i) { + + status = private_f_thread_condition_attribute_delete(&attributes->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(attributes->size, length, sizeof(f_thread_condition_attribute_t), (void **) & attributes->array); + + if (F_status_is_error_not(status)) { + attributes->size = length; + + if (attributes->used > attributes->size) { + attributes->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) + +#if !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) + f_status_t private_f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < attributes->size; ++i) { + + status = private_f_thread_condition_attribute_delete(&attributes->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(attributes->size, length, sizeof(f_thread_condition_attribute_t), (void **) & attributes->array); + + if (F_status_is_error_not(status)) { + attributes->size = length; + + if (attributes->used > attributes->size) { + attributes->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) + +#if !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) || !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) || !defined(_di_f_thread_conditions_resize_) + f_status_t private_f_thread_condition_delete(f_thread_condition_t *condition) { + + const int error = pthread_cond_destroy(condition); + + if (error) { + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) || !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) || !defined(_di_f_thread_conditions_resize_) + +#if !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) + f_status_t private_f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < conditions->size; ++i) { + + status = private_f_thread_condition_delete(&conditions->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_adjust(conditions->size, length, sizeof(f_thread_condition_t), (void **) & conditions->array); + + if (F_status_is_error_not(status)) { + conditions->size = length; + + if (conditions->used > conditions->size) { + conditions->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) + +#if !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) + f_status_t private_f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions) { + f_status_t status = F_none; + + for (f_array_length_t i = length; i < conditions->size; ++i) { + + status = private_f_thread_condition_delete(&conditions->array[i]); + if (F_status_is_error(status)) return status; + } // for + + status = f_memory_resize(conditions->size, length, sizeof(f_thread_condition_t), (void **) & conditions->array); + + if (F_status_is_error_not(status)) { + conditions->size = length; + + if (conditions->used > conditions->size) { + conditions->used = length; + } + } + + return status; + } +#endif // !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) + #if !defined(_di_f_thread_mutexs_adjust_) || !defined(_di_f_thread_mutexs_decimate_by_) || !defined(_di_f_thread_mutexs_decrease_) || !defined(_di_f_thread_mutexs_decrease_by_) || !defined(_di_f_thread_mutexs_increase_) || !defined(_di_f_thread_mutexs_increase_by_) || !defined(_di_f_thread_mutexs_resize_) f_status_t private_f_thread_mutex_delete(f_thread_mutex_t *mutex) { diff --git a/level_0/f_thread/c/private-thread.h b/level_0/f_thread/c/private-thread.h index e23ff83..f34b41b 100644 --- a/level_0/f_thread/c/private-thread.h +++ b/level_0/f_thread/c/private-thread.h @@ -30,6 +30,8 @@ extern "C" { * * F_failure (with error bit) on error. * + * @see pthread_attr_destroy() + * * @see f_thread_attributes_adjust() * @see f_thread_attributes_decimate_by() * @see f_thread_attributes_decrease() @@ -103,6 +105,158 @@ extern "C" { * * @param length * The new size to use. + * @param attribute + * The attribute to adjust. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_condattr_destroy() + * + * @see f_thread_condition_attributes_adjust() + * @see f_thread_condition_attributes_decimate_by() + * @see f_thread_condition_attributes_decrease() + * @see f_thread_condition_attributes_decrease_by() + * @see f_thread_condition_attributes_increase() + * @see f_thread_condition_attributes_increase_by() + * @see f_thread_condition_attributes_resize() + */ +#if !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) || !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) || !defined(_di_f_thread_condition_attributes_resize_) + extern f_status_t private_f_thread_condition_attribute_delete(f_thread_condition_attribute_t *attribute) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) || !defined(_di_f_thread_condition_attributes_decrease_) || !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) || !defined(_di_f_thread_condition_attributes_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param attributes + * The attributes to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_condition_attributes_adjust() + * @see f_thread_condition_attributes_decimate_by() + */ +#if !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) + extern f_status_t private_f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_condition_attributes_adjust_) || !defined(_di_f_thread_condition_attributes_decimate_by_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param attributes + * The attributes to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_condition_attributes_decrease_by() + * @see f_thread_condition_attributes_increase() + * @see f_thread_condition_attributes_increase_by() + */ +#if !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) + extern f_status_t private_f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_condition_attributes_decrease_by_) || !defined(_di_f_thread_condition_attributes_increase_) || !defined(_di_f_thread_condition_attributes_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param conditions + * The conditions to adjust. + * + * @return + * F_none on success. + * + * F_failure (with error bit) on error. + * + * @see pthread_cond_destroy() + * + * @see f_thread_conditions_adjust() + * @see f_thread_conditions_decimate_by() + * @see f_thread_conditions_decrease() + * @see f_thread_conditions_decrease_by() + * @see f_thread_conditions_increase() + * @see f_thread_conditions_increase_by() + * @see f_thread_conditions_resize() + */ +#if !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) || !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) || !defined(_di_f_thread_conditions_resize_) + extern f_status_t private_f_thread_condition_delete(f_thread_condition_t *condition) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) || !defined(_di_f_thread_conditions_decrease_) || !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) || !defined(_di_f_thread_conditions_resize_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param conditions + * The conditions to adjust. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_adjust(). + * + * @see f_memory_adjust() + * @see f_thread_conditions_adjust() + * @see f_thread_conditions_decimate_by() + */ +#if !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) + extern f_status_t private_f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_conditions_adjust_) || !defined(_di_f_thread_conditions_decimate_by_) + +/** + * Private implementation for resizing. + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. + * @param conditions + * The conditions to resize. + * + * @return + * F_none on success. + * + * Errors (with error bit) from: f_memory_resize(). + * + * @see f_memory_resize() + * @see f_thread_conditions_decrease_by() + * @see f_thread_conditions_increase() + * @see f_thread_conditions_increase_by() + */ +#if !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) + extern f_status_t private_f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions) f_gcc_attribute_visibility_internal; +#endif // !defined(_di_f_thread_conditions_decrease_by_) || !defined(_di_f_thread_conditions_increase_) || !defined(_di_f_thread_conditions_increase_by_) + +/** + * Private implementation for deleting (and destroying). + * + * Intended to be shared to each of the different implementation variations. + * + * @param length + * The new size to use. * @param mutexs * The mutexs to adjust. * @@ -111,6 +265,8 @@ extern "C" { * * F_failure (with error bit) on error. * + * @see pthread_mutex_destroy() + * * @see f_thread_mutexs_adjust() * @see f_thread_mutexs_decimate_by() * @see f_thread_mutexs_decrease() diff --git a/level_0/f_thread/c/thread-common.h b/level_0/f_thread/c/thread-common.h index 4131614..5bfb6fd 100644 --- a/level_0/f_thread/c/thread-common.h +++ b/level_0/f_thread/c/thread-common.h @@ -67,9 +67,11 @@ extern "C" { #ifndef _di_f_thread_condition_t_ typedef pthread_cond_t f_thread_condition_t; - #define f_thread_condition_t_initialize 0 + #define f_thread_condition_t_initialize PTHREAD_COND_INITIALIZER; #define f_macro_thread_condition_t_clear(condition) condition = 0 + + #define f_macro_thread_condition_t_delete_simple(condition) f_thread_condition_delete(&condition); #endif // _di_f_thread_condition_t_ /** @@ -89,19 +91,65 @@ extern "C" { #define f_thread_conditions_t_initialize { 0, 0, 0 } - #define f_macro_thread_conditions_t_resize(status, conditions, length) f_macro_memory_structure_resize(status, conditions, f_thread_condition_t, length) - #define f_macro_thread_conditions_t_adjust(status, conditions, length) f_macro_memory_structure_adjust(status, conditions, f_thread_condition_t, length) + #define f_macro_thread_conditions_t_clear(conditions) f_macro_memory_structure_clear(conditions) + + #define f_macro_thread_conditions_t_resize(status, conditions, length) status = f_thread_conditions_resize(length, &conditions); + #define f_macro_thread_conditions_t_adjust(status, conditions, length) status = f_thread_conditions_adjust(length, &conditions); - #define f_macro_thread_conditions_t_delete_simple(conditions) f_macro_memory_structure_delete_simple(conditions, f_thread_condition_t) - #define f_macro_thread_conditions_t_destroy_simple(conditions) f_macro_memory_structure_destroy_simple(conditions, f_thread_condition_t) + #define f_macro_thread_conditions_t_delete_simple(conditions) f_thread_conditions_resize(0, &conditions); + #define f_macro_thread_conditions_t_destroy_simple(conditions) f_thread_conditions_adjust(0, &conditions); - #define f_macro_thread_conditions_t_increase(status, conditions) f_macro_memory_structure_increase(status, conditions, f_thread_condition_t) - #define f_macro_thread_conditions_t_increase_by(status, conditions, amount) f_macro_memory_structure_increase_by(status, conditions, f_thread_condition_t, amount) - #define f_macro_thread_conditions_t_decrease_by(status, conditions, amount) f_macro_memory_structure_decrease_by(status, conditions, f_thread_condition_t, amount) - #define f_macro_thread_conditions_t_decimate_by(status, conditions, amount) f_macro_memory_structure_decimate_by(status, conditions, f_thread_condition_t, amount) + #define f_macro_thread_conditions_t_increase(status, conditions) status = f_thread_conditions_increase(conditions); + #define f_macro_thread_conditions_t_increase_by(status, conditions, amount) status = f_thread_conditions_increase_by(amount, conditions); + #define f_macro_thread_conditions_t_decrease_by(status, conditions, amount) status = f_thread_conditions_decrease_by(amount, conditions); + #define f_macro_thread_conditions_t_decimate_by(status, conditions, amount) status = f_thread_conditions_decimate_by(amount, conditions); #endif // _di_f_thread_conditions_t_ /** + * A typedef representing pthread_cond_t. + */ +#ifndef _di_f_thread_condition_attribute_t_ + typedef pthread_condattr_t f_thread_condition_attribute_t; + + #define f_thread_condition_attribute_t_initialize 0; + + #define f_macro_thread_condition_attribute_t_clear(attribute) attribute = 0 + + #define f_macro_thread_condition_attribute_t_delete_simple(attribute) f_thread_condition_attribute_delete(&attribute); +#endif // _di_f_thread_condition_attribute_t_ + +/** + * An array of thread condition attributes. + * + * array: the array of f_thread_condition_attribute_t. + * size: total amount of allocated space. + * used: total number of allocated spaces used. + */ +#ifndef _di_f_thread_condition_attributes_t_ + typedef struct { + f_thread_condition_attribute_t *array; + + f_array_length_t size; + f_array_length_t used; + } f_thread_condition_attributes_t; + + #define f_thread_condition_attributes_t_initialize { 0, 0, 0 } + + #define f_macro_thread_condition_attributes_t_clear(attributes) f_macro_memory_structure_clear(attributes) + + #define f_macro_thread_condition_attributes_t_resize(status, attributes, length) status = f_thread_condition_attributes_resize(length, &attributes); + #define f_macro_thread_condition_attributes_t_adjust(status, attributes, length) status = f_thread_condition_attributes_adjust(length, &attributes); + + #define f_macro_thread_condition_attributes_t_delete_simple(attributes) f_thread_condition_attributes_resize(0, &condition_attributes); + #define f_macro_thread_condition_attributes_t_destroy_simple(attributes) f_thread_condition_attributes_adjust(0, &condition_attributes); + + #define f_macro_thread_condition_attributes_t_increase(status, attributes) status = f_thread_condition_attributes_increase(attributes); + #define f_macro_thread_condition_attributes_t_increase_by(status, attributes, amount) status = f_thread_condition_attributes_increase_by(amount, attributes); + #define f_macro_thread_condition_attributes_t_decrease_by(status, attributes, amount) status = f_thread_condition_attributes_decrease_by(amount, attributes); + #define f_macro_thread_condition_attributes_t_decimate_by(status, attributes, amount) status = f_thread_condition_attributes_decimate_by(amount, attributes); +#endif // _di_f_thread_condition_attributes_t_ + +/** * A typedef representing pthread_t. */ #ifndef _di_f_thread_id_t_ diff --git a/level_0/f_thread/c/thread.c b/level_0/f_thread/c/thread.c index 1819f98..fda017d 100644 --- a/level_0/f_thread/c/thread.c +++ b/level_0/f_thread/c/thread.c @@ -64,9 +64,6 @@ extern "C" { #ifndef _di_f_thread_attribute_create_ f_status_t f_thread_attribute_create(f_thread_attribute_t *attribute) { - #ifndef _di_level_0_parameter_checking_ - if (!attribute) return F_status_set_error(F_parameter); - #endif // _di_level_0_parameter_checking_ const int error = pthread_attr_init(attribute); @@ -562,6 +559,159 @@ extern "C" { } #endif // _di_f_thread_compare_ +#ifndef _di_f_thread_condition_attribute_create_ + f_status_t f_thread_condition_attribute_create(f_thread_condition_attribute_t *attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_condattr_init(attribute); + + if (error) { + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_attribute_create_ + +#ifndef _di_f_thread_condition_attribute_delete_ + f_status_t f_thread_condition_attribute_delete(f_thread_condition_attribute_t *condition_attribute) { + #ifndef _di_level_0_parameter_checking_ + if (!condition_attribute) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_attribute_delete(condition_attribute); + } +#endif // _di_f_thread_condition_attribute_delete_ + +#ifndef _di_f_thread_condition_attributes_adjust_ + f_status_t f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_attributes_adjust(length, attributes); + } +#endif // _di_f_thread_condition_attributes_adjust_ + +#ifndef _di_f_thread_condition_attributes_decimate_by_ + f_status_t f_thread_condition_attributes_decimate_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->size - amount > 0) { + return private_f_thread_condition_attributes_adjust(attributes->size - amount, attributes); + } + + return private_f_thread_condition_attributes_adjust(0, attributes); + } +#endif // _di_f_thread_condition_attributes_decimate_by_ + +#ifndef _di_f_thread_condition_attributes_decrease_by_ + f_status_t f_thread_condition_attributes_decrease_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->size - amount > 0) { + return private_f_thread_condition_attributes_resize(attributes->size - amount, attributes); + } + + return private_f_thread_condition_attributes_resize(0, attributes); + } +#endif // _di_f_thread_condition_attributes_decrease_by_ + +#ifndef _di_f_thread_condition_attributes_increase_ + f_status_t f_thread_condition_attributes_increase(f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->used + 1 > attributes->size) { + f_array_length_t size = attributes->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (attributes->used + 1 > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + size = f_array_length_t_size; + } + + return private_f_thread_condition_attributes_resize(size, attributes); + } + + return F_data_not; + } +#endif // _di_f_thread_condition_attributes_increase_ + +#ifndef _di_f_thread_condition_attributes_increase_by_ + f_status_t f_thread_condition_attributes_increase_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (attributes->used + amount > attributes->size) { + if (attributes->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_condition_attributes_resize(attributes->used + amount, attributes); + } + + return F_data_not; + } +#endif // _di_f_thread_condition_attributes_increase_by_ + +#ifndef _di_f_thread_condition_attributes_resize_ + f_status_t f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes) { + #ifndef _di_level_0_parameter_checking_ + if (!attributes) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_attributes_resize(length, attributes); + } +#endif // _di_f_thread_condition_attributes_resize_ + +#ifndef _di_f_thread_condition_create_ + f_status_t f_thread_condition_create(const f_thread_condition_attribute_t *attribute, f_thread_condition_t *condition) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + const int error = pthread_cond_init(condition, attribute); + + if (error) { + if (error == EAGAIN) return F_status_set_error(F_resource_not); + if (error == EBUSY) return F_status_set_error(F_busy); + if (error == EINVAL) return F_status_set_error(F_parameter); + if (error == ENOMEM) return F_status_set_error(F_memory_not); + + return F_status_set_error(F_failure); + } + + return F_none; + } +#endif // _di_f_thread_condition_create_ + +#ifndef _di_f_thread_condition_delete_ + f_status_t f_thread_condition_delete(f_thread_condition_t *condition) { + #ifndef _di_level_0_parameter_checking_ + if (!condition) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_condition_delete(condition); + } +#endif // _di_f_thread_condition_delete_ + #ifndef _di_f_thread_condition_unblock_all_ f_status_t f_thread_condition_unblock_all(f_thread_condition_t *condition) { #ifndef _di_level_0_parameter_checking_ @@ -638,6 +788,99 @@ extern "C" { } #endif // _di_f_thread_condition_wait_timed_ +#ifndef _di_f_thread_conditions_adjust_ + f_status_t f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_conditions_adjust(length, conditions); + } +#endif // _di_f_thread_conditions_adjust_ + +#ifndef _di_f_thread_conditions_decimate_by_ + f_status_t f_thread_conditions_decimate_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->size - amount > 0) { + return private_f_thread_conditions_adjust(conditions->size - amount, conditions); + } + + return private_f_thread_conditions_adjust(0, conditions); + } +#endif // _di_f_thread_conditions_decimate_by_ + +#ifndef _di_f_thread_conditions_decrease_by_ + f_status_t f_thread_conditions_decrease_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->size - amount > 0) { + return private_f_thread_conditions_resize(conditions->size - amount, conditions); + } + + return private_f_thread_conditions_resize(0, conditions); + } +#endif // _di_f_thread_conditions_decrease_by_ + +#ifndef _di_f_thread_conditions_increase_ + f_status_t f_thread_conditions_increase(f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->used + 1 > conditions->size) { + f_array_length_t size = conditions->used + f_memory_default_allocation_step; + + if (size > f_array_length_t_size) { + if (conditions->used + 1 > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + size = f_array_length_t_size; + } + + return private_f_thread_conditions_resize(size, conditions); + } + + return F_data_not; + } +#endif // _di_f_thread_conditions_increase_ + +#ifndef _di_f_thread_conditions_increase_by_ + f_status_t f_thread_conditions_increase_by(const f_array_length_t amount, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!amount) return F_status_set_error(F_parameter); + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + if (conditions->used + amount > conditions->size) { + if (conditions->used + amount > f_array_length_t_size) { + return F_status_set_error(F_array_too_large); + } + + return private_f_thread_conditions_resize(conditions->used + amount, conditions); + } + + return F_data_not; + } +#endif // _di_f_thread_conditions_increase_by_ + +#ifndef _di_f_thread_conditions_resize_ + f_status_t f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions) { + #ifndef _di_level_0_parameter_checking_ + if (!conditions) return F_status_set_error(F_parameter); + #endif // _di_level_0_parameter_checking_ + + return private_f_thread_conditions_resize(length, conditions); + } +#endif // _di_f_thread_conditions_resize_ + #ifndef _di_f_thread_create_ f_status_t f_thread_create(const f_thread_attribute_t *attribute, f_thread_id_t *id, void *(*routine) (void *), void *argument) { #ifndef _di_level_0_parameter_checking_ diff --git a/level_0/f_thread/c/thread.h b/level_0/f_thread/c/thread.h index 436a86f..13e8e0d 100644 --- a/level_0/f_thread/c/thread.h +++ b/level_0/f_thread/c/thread.h @@ -104,7 +104,8 @@ extern "C" { * Create (initialize) a thread attribute structure. * * @param attribute - * The thread attributes to create. + * (optional) The attribute to set. + * Set to NULL to not use (in which case the default attribute is used). * * @return * F_none on success. @@ -718,6 +719,215 @@ extern "C" { #endif // _di_f_thread_compare_ /** + * Initialize a attribute. + * + * @param attribute + * The attribute to set. + * This assigns the default to the attribute. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_condattr_init() + */ +#ifndef _di_f_thread_condition_attribute_create_ + extern f_status_t f_thread_condition_attribute_create(f_thread_condition_attribute_t *attribute); +#endif // _di_f_thread_condition_attribute_create_ + +/** + * Delete a thread attribute. + * + * The pthread_condattr_destroy() function has no distinction like the *_destroy() and the *_delete() used by the FLL project. + * Therefore there is only this function for both deleting and destroying. + * + * @param attribute + * The attribute to delete. + * + * @return + * F_none on success. + * + * F_busy (with error bit) if the attribute is busy. + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_cond_destroy() + */ +#ifndef _di_f_thread_condition_attribute_delete_ + extern f_status_t f_thread_condition_attribute_delete(f_thread_condition_attribute_t *attribute); +#endif // _di_f_thread_condition_attribute_delete_ + +/** + * Resize the string attributes array. + * + * @param length + * The new size to use. + * @param attributes + * The string attributes array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_condition_attributes_adjust_ + extern f_status_t f_thread_condition_attributes_adjust(const f_array_length_t length, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_adjust_ + +/** + * Resize the string attributes array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decimate the size by. + * @param attributes + * The string attributes array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_condition_attributes_decimate_by_ + extern f_status_t f_thread_condition_attributes_decimate_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_decimate_by_ + +/** + * Resize the string attributes array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param attributes + * The string attributes array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_condition_attributes_decrease_by_ + extern f_status_t f_thread_condition_attributes_decrease_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_decrease_by_ + +/** + * Increase the size of the string attributes array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param attributes + * The string attributes array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_condition_attributes_increase_ + extern f_status_t f_thread_condition_attributes_increase(f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_increase_ + +/** + * Resize the string attributes array to a larger size. + * + * This will resize making the string larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param attributes + * The string attributes array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + amount <= size). + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * F_array_too_large (with error bit) if the new array length is too large. + */ +#ifndef _di_f_thread_condition_attributes_increase_by_ + extern f_status_t f_thread_condition_attributes_increase_by(const f_array_length_t amount, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_increase_by_ + +/** + * Resize the string attributes array. + * + * @param length + * The new size to use. + * @param attributes + * The string attributes array to adjust. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_condition_attributes_resize_ + extern f_status_t f_thread_condition_attributes_resize(const f_array_length_t length, f_thread_condition_attributes_t *attributes); +#endif // _di_f_thread_condition_attributes_resize_ + +/** + * Initialize a condition. + * + * @param attribute + * (optional) The attribute to set. + * Set to NULL to not use (in which case the default attribute is used). + * @param condition + * The condition to wait on. + * + * @return + * F_none on success. + * + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_cond_init() + */ +#ifndef _di_f_thread_condition_create_ + extern f_status_t f_thread_condition_create(const f_thread_condition_attribute_t *attribute, f_thread_condition_t *condition); +#endif // _di_f_thread_condition_create_ + +/** + * Delete a thread condition. + * + * The pthread_cond_destroy() function has no distinction like the *_destroy() and the *_delete() used by the FLL project. + * Therefore there is only this function for both deleting and destroying. + * + * @param condition + * The condition to delete. + * + * @return + * F_none on success. + * + * F_busy (with error bit) if the condition is busy. + * F_parameter (with error bit) if a parameter is invalid. + * F_failure (with error bit) on any other error. + * + * @see pthread_cond_destroy() + */ +#ifndef _di_f_thread_condition_delete_ + extern f_status_t f_thread_condition_delete(f_thread_condition_t *condition); +#endif // _di_f_thread_condition_delete_ + +/** * Unblock all threads waiting on a condition. * * @param condition @@ -804,7 +1014,132 @@ extern "C" { #endif // _di_f_thread_condition_wait_timed_ /** - * Get the user account by the user id. + * Resize the string conditions array. + * + * @param length + * The new size to use. + * @param conditions + * The string conditions array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_conditions_adjust_ + extern f_status_t f_thread_conditions_adjust(const f_array_length_t length, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_adjust_ + +/** + * Resize the string conditions array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decimate the size by. + * @param conditions + * The string conditions array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_conditions_decimate_by_ + extern f_status_t f_thread_conditions_decimate_by(const f_array_length_t amount, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_decimate_by_ + +/** + * Resize the string conditions array to a smaller size. + * + * This will resize making the array smaller based on (size - given length). + * If the given length is too small, then the resize will fail. + * This will not shrink the size to less than 0. + * + * @param amount + * A positive number representing how much to decrease the size by. + * @param conditions + * The string conditions array to resize. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_conditions_decrease_by_ + extern f_status_t f_thread_conditions_decrease_by(const f_array_length_t amount, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_decrease_by_ + +/** + * Increase the size of the string conditions array, but only if necessary. + * + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param conditions + * The string conditions array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + 1 <= size). + * + * F_array_too_large (with error bit) if the new array length is too large. + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_conditions_increase_ + extern f_status_t f_thread_conditions_increase(f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_increase_ + +/** + * Resize the string conditions array to a larger size. + * + * This will resize making the string larger based on the given length. + * If the given length is too large for the buffer, then attempt to set max buffer size (f_array_length_t_size). + * If already set to the maximum buffer size, then the resize will fail. + * + * @param amount + * A positive number representing how much to increase the size by. + * @param conditions + * The string conditions array to resize. + * + * @return + * F_none on success. + * F_data_not on success, but there is no reason to increase size (used + amount <= size). + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + * F_array_too_large (with error bit) if the new array length is too large. + */ +#ifndef _di_f_thread_conditions_increase_by_ + extern f_status_t f_thread_conditions_increase_by(const f_array_length_t amount, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_increase_by_ + +/** + * Resize the string conditions array. + * + * @param length + * The new size to use. + * @param conditions + * The string conditions array to adjust. + * + * @return + * F_none on success. + * + * F_memory_not (with error bit) on out of memory. + * F_parameter (with error bit) if a parameter is invalid. + */ +#ifndef _di_f_thread_conditions_resize_ + extern f_status_t f_thread_conditions_resize(const f_array_length_t length, f_thread_conditions_t *conditions); +#endif // _di_f_thread_conditions_resize_ + +/** + * Create a thread. * * @param attribute * (optional) The thread attributes. -- 1.8.3.1