From 79a6622910f7cdbf66fdefb398128b6859b0ae8a Mon Sep 17 00:00:00 2001 From: Brice Videau Date: Fri, 10 May 2024 11:33:18 -0500 Subject: [PATCH] Prevent parameters inclusion in several contexts. --- include/cconfigspace/configuration_space.h | 5 ++-- include/cconfigspace/feature_space.h | 3 +- include/cconfigspace/objective_space.h | 3 +- src/configuration_space.c | 6 +++- src/context_internal.h | 6 ++++ src/feature_space.c | 5 +++- src/objective_space.c | 5 +++- src/parameter_internal.h | 33 ++++++++++++++++++++++ 8 files changed, 59 insertions(+), 7 deletions(-) diff --git a/include/cconfigspace/configuration_space.h b/include/cconfigspace/configuration_space.h index aac9ae08..2bb15c89 100644 --- a/include/cconfigspace/configuration_space.h +++ b/include/cconfigspace/configuration_space.h @@ -40,8 +40,9 @@ extern "C" { * rng is not NULL and is not a valid CCS rng * @return #CCS_RESULT_ERROR_INVALID_PARAMETER if a parameter's type is * CCS_PARAMETER_TYPE_STRING; or if a parameter appears more than once in \p - * parameters; or if two or more parameters share the same name; or if an - * expression references a parameter that is not in the configuration space + * parameters; or if two or more parameters share the same name; or if a + * paramater is already part of another context; or if an expression references + * a parameter that is not in the configuration space * @return #CCS_RESULT_ERROR_INVALID_CONFIGURATION if adding one of the provided * forbidden clause would render the default configuration invalid * @return #CCS_RESULT_ERROR_INVALID_GRAPH if the addition of the conditions diff --git a/include/cconfigspace/feature_space.h b/include/cconfigspace/feature_space.h index 32cf9fce..4b375920 100644 --- a/include/cconfigspace/feature_space.h +++ b/include/cconfigspace/feature_space.h @@ -23,7 +23,8 @@ extern "C" { * @return #CCS_RESULT_ERROR_INVALID_OBJECT if a parameter is not a valid CCS * parameter * @return #CCS_RESULT_ERROR_INVALID_PARAMETER if a parameter appears more than - * once in \p parameters; or if two or more parameters share the same name + * once in \p parameters; or if two or more parameters share the same name; or + * if a paramater is already part of another context * @return #CCS_RESULT_ERROR_OUT_OF_MEMORY if there was a lack of memory to * allocate the new feature space * @remarks diff --git a/include/cconfigspace/objective_space.h b/include/cconfigspace/objective_space.h index 65a8db29..061c5147 100644 --- a/include/cconfigspace/objective_space.h +++ b/include/cconfigspace/objective_space.h @@ -54,7 +54,8 @@ typedef enum ccs_objective_type_e ccs_objective_type_t; * parameter; or if an expressions is not a valid CCS expression * @return #CCS_RESULT_ERROR_INVALID_PARAMETER if a parameter appears more than * once in \p parameters; or if two or more parameters share the same name; or - * if an expression references a parameter that is not in \p parameters + * if a paramater is already part of another context; or if an expression + * references a parameter that is not in \p parameters * @return #CCS_RESULT_ERROR_OUT_OF_MEMORY if there was a lack of memory to * allocate the new objective space * @remarks diff --git a/src/configuration_space.c b/src/configuration_space.c index e7d479e7..14dfaacc 100644 --- a/src/configuration_space.c +++ b/src/configuration_space.c @@ -19,8 +19,12 @@ _ccs_configuration_space_del(ccs_object_t object) _ccs_configuration_space_data_t *data = configuration_space->data; for (size_t i = 0; i < data->num_parameters; i++) { - if (data->parameters[i]) + if (data->parameters[i]) { + _ccs_parameter_release_ownership( + data->parameters[i], + (ccs_context_t)configuration_space); ccs_release_object(data->parameters[i]); + } if (data->conditions[i]) ccs_release_object(data->conditions[i]); if (data->parents[i]) diff --git a/src/context_internal.h b/src/context_internal.h index a426ece9..ed952158 100644 --- a/src/context_internal.h +++ b/src/context_internal.h @@ -144,6 +144,7 @@ _ccs_context_add_parameter( ccs_parameter_t parameter, size_t index) { + ccs_result_t err = CCS_RESULT_SUCCESS; const char *name; size_t sz_name; _ccs_parameter_index_hash_t *parameter_hash; @@ -169,8 +170,13 @@ _ccs_context_add_parameter( sz_name, parameter_hash); CCS_VALIDATE(ccs_retain_object(parameter)); + CCS_VALIDATE_ERR_GOTO( + err, _ccs_parameter_take_ownership(parameter, context), error); context->data->parameters[index] = parameter; return CCS_RESULT_SUCCESS; +error: + ccs_release_object(parameter); + return err; } #undef uthash_nonfatal_oom diff --git a/src/feature_space.c b/src/feature_space.c index 11f30726..0e1b90d3 100644 --- a/src/feature_space.c +++ b/src/feature_space.c @@ -11,8 +11,11 @@ _ccs_feature_space_del(ccs_object_t object) ccs_parameter_t *parameters = feature_space->data->parameters; for (size_t i = 0; i < num_parameters; i++) - if (parameters[i]) + if (parameters[i]) { + _ccs_parameter_release_ownership( + parameters[i], (ccs_context_t)feature_space); ccs_release_object(parameters[i]); + } HASH_CLEAR(hh_name, feature_space->data->name_hash); HASH_CLEAR(hh_handle, feature_space->data->handle_hash); diff --git a/src/objective_space.c b/src/objective_space.c index 690d8d31..f5865101 100644 --- a/src/objective_space.c +++ b/src/objective_space.c @@ -18,8 +18,11 @@ _ccs_objective_space_del(ccs_object_t object) if (search_space) ccs_release_object(search_space); for (size_t i = 0; i < num_parameters; i++) - if (parameters[i]) + if (parameters[i]) { + _ccs_parameter_release_ownership( + parameters[i], (ccs_context_t)objective_space); ccs_release_object(parameters[i]); + } for (size_t i = 0; i < num_objectives; i++) if (objectives[i].expression) diff --git a/src/parameter_internal.h b/src/parameter_internal.h index f9782194..fa47265b 100644 --- a/src/parameter_internal.h +++ b/src/parameter_internal.h @@ -52,6 +52,8 @@ struct _ccs_parameter_s { struct _ccs_parameter_common_data_s { ccs_parameter_type_t type; + // a weak erference to a context to prevent multiple inclusion + ccs_context_t ctx; const char *name; ccs_datum_t default_value; ccs_interval_t interval; @@ -155,4 +157,35 @@ _ccs_deserialize_bin_ccs_parameter_numerical_data( return CCS_RESULT_SUCCESS; } +static inline ccs_result_t +_ccs_parameter_take_ownership(ccs_parameter_t param, ccs_context_t ctx) +{ + ccs_result_t err = CCS_RESULT_SUCCESS; + _ccs_parameter_common_data_t *data = + (_ccs_parameter_common_data_t *)param->data; + CCS_OBJ_WRLOCK(param); + CCS_REFUTE_ERR_GOTO( + err, data->ctx, CCS_RESULT_ERROR_INVALID_PARAMETER, error); + data->ctx = ctx; +error: + CCS_OBJ_UNLOCK(param); + return err; +} + +static inline ccs_result_t +_ccs_parameter_release_ownership(ccs_parameter_t param, ccs_context_t ctx) +{ + ccs_result_t err = CCS_RESULT_SUCCESS; + _ccs_parameter_common_data_t *data = + (_ccs_parameter_common_data_t *)param->data; + CCS_OBJ_WRLOCK(param); + CCS_REFUTE_ERR_GOTO( + err, data->ctx != ctx, CCS_RESULT_ERROR_INVALID_PARAMETER, + error); + data->ctx = NULL; +error: + CCS_OBJ_UNLOCK(param); + return err; +} + #endif //_PARAMETER_INTERNAL_H