From 7fba736df9cef834dc8768f96a1f17a41b17d1b3 Mon Sep 17 00:00:00 2001 From: jp9000 Date: Tue, 21 Feb 2017 23:02:17 -0800 Subject: [PATCH] libobs/util: Use a mutex with config files --- libobs/util/config-file.c | 154 ++++++++++++++++++++++++++++---------- libobs/util/config-file.h | 24 +++--- 2 files changed, 126 insertions(+), 52 deletions(-) diff --git a/libobs/util/config-file.c b/libobs/util/config-file.c index 735afee72..98d8807ad 100644 --- a/libobs/util/config-file.c +++ b/libobs/util/config-file.c @@ -18,6 +18,7 @@ #include #include #include "config-file.h" +#include "threading.h" #include "platform.h" #include "base.h" #include "bmem.h" @@ -57,8 +58,19 @@ struct config_data { char *file; struct darray sections; /* struct config_section */ struct darray defaults; /* struct config_section */ + pthread_mutex_t mutex; }; +static inline bool init_mutex(config_t *config) +{ + pthread_mutexattr_t attr; + if (pthread_mutexattr_init(&attr) != 0) + return false; + if (pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE) != 0) + return false; + return pthread_mutex_init(&config->mutex, &attr) == 0; +} + config_t *config_create(const char *file) { struct config_data *config; @@ -70,6 +82,12 @@ config_t *config_create(const char *file) fclose(f); config = bzalloc(sizeof(struct config_data)); + + if (!init_mutex(config)) { + bfree(config); + return NULL; + } + config->file = bstrdup(file); return config; } @@ -278,6 +296,11 @@ int config_open(config_t **config, const char *file, if (!*config) return CONFIG_ERROR; + if (!init_mutex(*config)) { + bfree(*config); + return CONFIG_ERROR; + } + (*config)->file = bstrdup(file); errorcode = config_parse_file(&(*config)->sections, file, always_open); @@ -301,6 +324,11 @@ int config_open_string(config_t **config, const char *str) if (!*config) return CONFIG_ERROR; + if (!init_mutex(*config)) { + bfree(*config); + return CONFIG_ERROR; + } + (*config)->file = NULL; lexer_init(&lex); @@ -333,9 +361,13 @@ int config_save(config_t *config) dstr_init(&str); dstr_init(&tmp); + pthread_mutex_lock(&config->mutex); + f = os_fopen(config->file, "wb"); - if (!f) + if (!f) { + pthread_mutex_unlock(&config->mutex); return CONFIG_FILENOTFOUND; + } for (i = 0; i < config->sections.num; i++) { struct config_section *section = darray_item( @@ -371,6 +403,8 @@ int config_save(config_t *config) fwrite(str.array, 1, str.len, f); fclose(f); + pthread_mutex_unlock(&config->mutex); + dstr_free(&tmp); dstr_free(&str); @@ -391,6 +425,8 @@ int config_save_safe(config_t *config, const char *temp_ext, return CONFIG_ERROR; } + pthread_mutex_lock(&config->mutex); + dstr_copy(&temp_file, config->file); if (*temp_ext != '.') dstr_cat(&temp_file, "."); @@ -419,6 +455,7 @@ int config_save_safe(config_t *config, const char *temp_ext, os_rename(temp_file.array, file); cleanup: + pthread_mutex_unlock(&config->mutex); dstr_free(&temp_file); dstr_free(&backup_file); return ret; @@ -442,6 +479,7 @@ void config_close(config_t *config) darray_free(&config->defaults); darray_free(&config->sections); bfree(config->file); + pthread_mutex_destroy(&config->mutex); bfree(config); } @@ -453,14 +491,20 @@ size_t config_num_sections(config_t *config) const char *config_get_section(config_t *config, size_t idx) { struct config_section *section; + const char *name = NULL; + + pthread_mutex_lock(&config->mutex); if (idx >= config->sections.num) - return NULL; + goto unlock; section = darray_item(sizeof(struct config_section), &config->sections, idx); + name = section->name; - return section->name; +unlock: + pthread_mutex_unlock(&config->mutex); + return name; } static const struct config_item *config_find_item(const struct darray *sections, @@ -487,14 +531,16 @@ static const struct config_item *config_find_item(const struct darray *sections, return NULL; } -static void config_set_item(struct darray *sections, const char *section, - const char *name, char *value) +static void config_set_item(config_t *config, struct darray *sections, + const char *section, const char *name, char *value) { struct config_section *sec = NULL; struct config_section *array = sections->array; struct config_item *item; size_t i, j; + pthread_mutex_lock(&config->mutex); + for (i = 0; i < sections->num; i++) { struct config_section *cur_sec = array+i; struct config_item *items = cur_sec->items.array; @@ -506,7 +552,7 @@ static void config_set_item(struct darray *sections, const char *section, if (astrcmpi(item->name, name) == 0) { bfree(item->value); item->value = value; - return; + goto unlock; } } @@ -524,6 +570,9 @@ static void config_set_item(struct darray *sections, const char *section, item = darray_push_back_new(sizeof(struct config_item), &sec->items); item->name = bstrdup(name); item->value = value; + +unlock: + pthread_mutex_unlock(&config->mutex); } void config_set_string(config_t *config, const char *section, @@ -531,7 +580,8 @@ void config_set_string(config_t *config, const char *section, { if (!value) value = ""; - config_set_item(&config->sections, section, name, bstrdup(value)); + config_set_item(config, &config->sections, section, name, + bstrdup(value)); } void config_set_int(config_t *config, const char *section, @@ -540,7 +590,7 @@ void config_set_int(config_t *config, const char *section, struct dstr str; dstr_init(&str); dstr_printf(&str, "%"PRId64, value); - config_set_item(&config->sections, section, name, str.array); + config_set_item(config, &config->sections, section, name, str.array); } void config_set_uint(config_t *config, const char *section, @@ -549,14 +599,14 @@ void config_set_uint(config_t *config, const char *section, struct dstr str; dstr_init(&str); dstr_printf(&str, "%"PRIu64, value); - config_set_item(&config->sections, section, name, str.array); + config_set_item(config, &config->sections, section, name, str.array); } void config_set_bool(config_t *config, const char *section, const char *name, bool value) { char *str = bstrdup(value ? "true" : "false"); - config_set_item(&config->sections, section, name, str); + config_set_item(config, &config->sections, section, name, str); } void config_set_double(config_t *config, const char *section, @@ -564,7 +614,7 @@ void config_set_double(config_t *config, const char *section, { char *str = bzalloc(64); os_dtostr(value, str, 64); - config_set_item(&config->sections, section, name, str); + config_set_item(config, &config->sections, section, name, str); } void config_set_default_string(config_t *config, const char *section, @@ -572,7 +622,8 @@ void config_set_default_string(config_t *config, const char *section, { if (!value) value = ""; - config_set_item(&config->defaults, section, name, bstrdup(value)); + config_set_item(config, &config->defaults, section, name, + bstrdup(value)); } void config_set_default_int(config_t *config, const char *section, @@ -581,7 +632,7 @@ void config_set_default_int(config_t *config, const char *section, struct dstr str; dstr_init(&str); dstr_printf(&str, "%"PRId64, value); - config_set_item(&config->defaults, section, name, str.array); + config_set_item(config, &config->defaults, section, name, str.array); } void config_set_default_uint(config_t *config, const char *section, @@ -590,14 +641,14 @@ void config_set_default_uint(config_t *config, const char *section, struct dstr str; dstr_init(&str); dstr_printf(&str, "%"PRIu64, value); - config_set_item(&config->defaults, section, name, str.array); + config_set_item(config, &config->defaults, section, name, str.array); } void config_set_default_bool(config_t *config, const char *section, const char *name, bool value) { char *str = bstrdup(value ? "true" : "false"); - config_set_item(&config->defaults, section, name, str); + config_set_item(config, &config->defaults, section, name, str); } void config_set_default_double(config_t *config, const char *section, @@ -606,20 +657,25 @@ void config_set_default_double(config_t *config, const char *section, struct dstr str; dstr_init(&str); dstr_printf(&str, "%g", value); - config_set_item(&config->defaults, section, name, str.array); + config_set_item(config, &config->defaults, section, name, str.array); } -const char *config_get_string(const config_t *config, const char *section, +const char *config_get_string(config_t *config, const char *section, const char *name) { - const struct config_item *item = config_find_item(&config->sections, - section, name); + const struct config_item *item; + const char *value = NULL; + + pthread_mutex_lock(&config->mutex); + + item = config_find_item(&config->sections, section, name); if (!item) item = config_find_item(&config->defaults, section, name); - if (!item) - return NULL; + if (item) + value = item->value; - return item->value; + pthread_mutex_unlock(&config->mutex); + return value; } static inline int64_t str_to_int64(const char *str) @@ -644,7 +700,7 @@ static inline uint64_t str_to_uint64(const char *str) return strtoull(str, NULL, 10); } -int64_t config_get_int(const config_t *config, const char *section, +int64_t config_get_int(config_t *config, const char *section, const char *name) { const char *value = config_get_string(config, section, name); @@ -654,7 +710,7 @@ int64_t config_get_int(const config_t *config, const char *section, return 0; } -uint64_t config_get_uint(const config_t *config, const char *section, +uint64_t config_get_uint(config_t *config, const char *section, const char *name) { const char *value = config_get_string(config, section, name); @@ -664,7 +720,7 @@ uint64_t config_get_uint(const config_t *config, const char *section, return 0; } -bool config_get_bool(const config_t *config, const char *section, +bool config_get_bool(config_t *config, const char *section, const char *name) { const char *value = config_get_string(config, section, name); @@ -675,7 +731,7 @@ bool config_get_bool(const config_t *config, const char *section, return false; } -double config_get_double(const config_t *config, const char *section, +double config_get_double(config_t *config, const char *section, const char *name) { const char *value = config_get_string(config, section, name); @@ -689,6 +745,9 @@ bool config_remove_value(config_t *config, const char *section, const char *name) { struct darray *sections = &config->sections; + bool success = false; + + pthread_mutex_lock(&config->mutex); for (size_t i = 0; i < sections->num; i++) { struct config_section *sec = darray_item( @@ -706,27 +765,34 @@ bool config_remove_value(config_t *config, const char *section, config_item_free(item); darray_erase(sizeof(struct config_item), &sec->items, j); - return true; + success = true; + goto unlock; } } } - return false; +unlock: + pthread_mutex_unlock(&config->mutex); + return success; } -const char *config_get_default_string(const config_t *config, +const char *config_get_default_string(config_t *config, const char *section, const char *name) { const struct config_item *item; + const char *value = NULL; + + pthread_mutex_lock(&config->mutex); item = config_find_item(&config->defaults, section, name); - if (!item) - return NULL; + if (item) + value = item->value; - return item->value; + pthread_mutex_unlock(&config->mutex); + return value; } -int64_t config_get_default_int(const config_t *config, const char *section, +int64_t config_get_default_int(config_t *config, const char *section, const char *name) { const char *value = config_get_default_string(config, section, name); @@ -736,7 +802,7 @@ int64_t config_get_default_int(const config_t *config, const char *section, return 0; } -uint64_t config_get_default_uint(const config_t *config, const char *section, +uint64_t config_get_default_uint(config_t *config, const char *section, const char *name) { const char *value = config_get_default_string(config, section, name); @@ -746,7 +812,7 @@ uint64_t config_get_default_uint(const config_t *config, const char *section, return 0; } -bool config_get_default_bool(const config_t *config, const char *section, +bool config_get_default_bool(config_t *config, const char *section, const char *name) { const char *value = config_get_default_string(config, section, name); @@ -757,7 +823,7 @@ bool config_get_default_bool(const config_t *config, const char *section, return false; } -double config_get_default_double(const config_t *config, const char *section, +double config_get_default_double(config_t *config, const char *section, const char *name) { const char *value = config_get_default_string(config, section, name); @@ -767,15 +833,23 @@ double config_get_default_double(const config_t *config, const char *section, return 0.0; } -bool config_has_user_value(const config_t *config, const char *section, +bool config_has_user_value(config_t *config, const char *section, const char *name) { - return config_find_item(&config->sections, section, name) != NULL; + bool success; + pthread_mutex_lock(&config->mutex); + success = config_find_item(&config->sections, section, name) != NULL; + pthread_mutex_unlock(&config->mutex); + return success; } -bool config_has_default_value(const config_t *config, const char *section, +bool config_has_default_value(config_t *config, const char *section, const char *name) { - return config_find_item(&config->defaults, section, name) != NULL; + bool success; + pthread_mutex_lock(&config->mutex); + success = config_find_item(&config->defaults, section, name) != NULL; + pthread_mutex_unlock(&config->mutex); + return success; } diff --git a/libobs/util/config-file.h b/libobs/util/config-file.h index f9002d060..c8bc31a6d 100644 --- a/libobs/util/config-file.h +++ b/libobs/util/config-file.h @@ -64,15 +64,15 @@ EXPORT void config_set_bool(config_t *config, const char *section, EXPORT void config_set_double(config_t *config, const char *section, const char *name, double value); -EXPORT const char *config_get_string(const config_t *config, +EXPORT const char *config_get_string(config_t *config, const char *section, const char *name); -EXPORT int64_t config_get_int(const config_t *config, const char *section, +EXPORT int64_t config_get_int(config_t *config, const char *section, const char *name); -EXPORT uint64_t config_get_uint(const config_t *config, const char *section, +EXPORT uint64_t config_get_uint(config_t *config, const char *section, const char *name); -EXPORT bool config_get_bool(const config_t *config, const char *section, +EXPORT bool config_get_bool(config_t *config, const char *section, const char *name); -EXPORT double config_get_double(const config_t *config, const char *section, +EXPORT double config_get_double(config_t *config, const char *section, const char *name); EXPORT bool config_remove_value(config_t *config, const char *section, @@ -107,20 +107,20 @@ EXPORT void config_set_default_double(config_t *config, const char *section, /* These functions allow you to get the current default values rather than get * the actual values. Probably almost never really needed */ -EXPORT const char *config_get_default_string(const config_t *config, +EXPORT const char *config_get_default_string(config_t *config, const char *section, const char *name); -EXPORT int64_t config_get_default_int(const config_t *config, +EXPORT int64_t config_get_default_int(config_t *config, const char *section, const char *name); -EXPORT uint64_t config_get_default_uint(const config_t *config, +EXPORT uint64_t config_get_default_uint(config_t *config, const char *section, const char *name); -EXPORT bool config_get_default_bool(const config_t *config, +EXPORT bool config_get_default_bool(config_t *config, const char *section, const char *name); -EXPORT double config_get_default_double(const config_t *config, +EXPORT double config_get_default_double(config_t *config, const char *section, const char *name); -EXPORT bool config_has_user_value(const config_t *config, +EXPORT bool config_has_user_value(config_t *config, const char *section, const char *name); -EXPORT bool config_has_default_value(const config_t *config, +EXPORT bool config_has_default_value(config_t *config, const char *section, const char *name); #ifdef __cplusplus