瀏覽代碼

libobs/util: Use a mutex with config files

jp9000 8 年之前
父節點
當前提交
7fba736df9
共有 2 個文件被更改,包括 126 次插入52 次删除
  1. 114 40
      libobs/util/config-file.c
  2. 12 12
      libobs/util/config-file.h

+ 114 - 40
libobs/util/config-file.c

@@ -18,6 +18,7 @@
 #include <stdio.h>
 #include <wchar.h>
 #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;
 }
 

+ 12 - 12
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