summaryrefslogtreecommitdiffstats
path: root/options
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2019-07-13 00:38:28 +0200
committerwm4 <wm4@nowhere>2019-09-19 20:37:05 +0200
commit059262c7466b4de5349aa0153312b0f44f9ef8ef (patch)
tree6c8ce0c41e250dfa368893bf7b8934ba2f74e856 /options
parent98627d3a32e993ebdaa1598834f2057d9952c7e4 (diff)
downloadmpv-059262c7466b4de5349aa0153312b0f44f9ef8ef.tar.bz2
mpv-059262c7466b4de5349aa0153312b0f44f9ef8ef.tar.xz
m_config: move group list to internal context
This is good because a private thing is not so public anymore, and it's also preparation for further changes. Some tricky memory management issues: m_config_data (i.e. config->data) now depends on m_config_shadow, instead of m_config. In particular, free_option_data() accesses the m_config_shadow.groups array. Obviously it must be freed before m_config_shadow.
Diffstat (limited to 'options')
-rw-r--r--options/m_config.c88
-rw-r--r--options/m_config.h7
2 files changed, 53 insertions, 42 deletions
diff --git a/options/m_config.c b/options/m_config.c
index e461602023..92cb2be950 100644
--- a/options/m_config.c
+++ b/options/m_config.c
@@ -57,6 +57,13 @@ static const union m_option_value default_value;
struct m_config_shadow {
struct m_config *root;
pthread_mutex_t lock;
+ // -- immutable after init
+ // List of m_sub_options instances.
+ // Index 0 is the top-level and is always present.
+ // Immutable after init.
+ // Invariant: a parent is always at a lower index than any of its children.
+ struct m_config_group *groups;
+ int num_groups;
// -- protected by lock
struct m_config_data *data; // protected shadow copy of the option data
struct m_config_cache **listeners;
@@ -81,6 +88,7 @@ struct m_config_group {
// and copies for m_config_cache.
struct m_config_data {
struct m_config *root; // root config (with up-to-date data)
+ struct m_config_shadow *shadow; // option definitions etc.
int group_index; // start index into m_config.groups[]
struct m_group_data *gdata; // user struct allocation (our copy of data)
int num_gdata; // (group_index+num_gdata = end index)
@@ -197,8 +205,8 @@ static void alloc_group(struct m_config_data *data, int group_index,
struct m_config_data *copy)
{
assert(group_index == data->group_index + data->num_gdata);
- assert(group_index < data->root->num_groups);
- struct m_config_group *group = &data->root->groups[group_index];
+ assert(group_index < data->shadow->num_groups);
+ struct m_config_group *group = &data->shadow->groups[group_index];
const struct m_sub_options *opts = group->group;
MP_TARRAY_GROW(data, data->gdata, data->num_gdata);
@@ -248,7 +256,8 @@ static void free_option_data(void *p)
for (int i = 0; i < data->num_gdata; i++) {
struct m_group_data *gdata = &data->gdata[i];
- struct m_config_group *group = &data->root->groups[data->group_index + i];
+ struct m_config_group *group =
+ &data->shadow->groups[data->group_index + i];
for (int n = group->co_index; n < group->co_end_index; n++) {
struct m_config_option *co = &data->root->opts[n];
@@ -268,14 +277,17 @@ static struct m_config_data *allocate_option_data(void *ta_parent,
int group_index,
struct m_config_data *copy)
{
- assert(group_index >= 0 && group_index < root->num_groups);
+ struct m_config_shadow *shadow = root->shadow;
+
+ assert(group_index >= 0 && group_index < shadow->num_groups);
struct m_config_data *data = talloc_zero(ta_parent, struct m_config_data);
talloc_set_destructor(data, free_option_data);
data->root = root;
+ data->shadow = shadow;
data->group_index = group_index;
- struct m_config_group *root_group = &root->groups[group_index];
+ struct m_config_group *root_group = &shadow->groups[group_index];
assert(root_group->group_count > 0);
for (int n = group_index; n < group_index + root_group->group_count; n++)
@@ -292,14 +304,15 @@ static void config_destroy(void *p)
struct m_config *config = p;
m_config_restore_backups(config);
+ talloc_free(config->data);
+
if (config->shadow) {
// must all have been unregistered
assert(config->shadow->num_listeners == 0);
+ talloc_free(config->shadow->data);
pthread_mutex_destroy(&config->shadow->lock);
talloc_free(config->shadow);
}
-
- talloc_free(config->data);
}
struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,
@@ -310,6 +323,10 @@ struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,
talloc_set_destructor(config, config_destroy);
*config = (struct m_config){.log = log,};
+ config->shadow = talloc_zero(NULL, struct m_config_shadow);
+ pthread_mutex_init(&config->shadow->lock, NULL);
+ config->shadow->root = config;
+
struct m_sub_options *subopts = talloc_ptrtype(config, subopts);
*subopts = (struct m_sub_options){
.opts = options,
@@ -324,6 +341,9 @@ struct m_config *m_config_new(void *talloc_ctx, struct mp_log *log,
config->data = allocate_option_data(config, config, 0, NULL);
config->optstruct = config->data->gdata[0].udata;
+ config->shadow->data =
+ allocate_option_data(config->shadow, config, 0, config->data);
+
for (int n = 0; n < config->num_opts; n++) {
struct m_config_option *co = &config->opts[n];
struct m_group_data *gdata = m_config_gdata(config->data, co->group_index);
@@ -359,11 +379,10 @@ static const struct m_config_group *find_group(struct mpv_global *global,
const struct m_option *cfg)
{
struct m_config_shadow *shadow = global->config;
- struct m_config *root = shadow->root;
- for (int n = 0; n < root->num_groups; n++) {
- if (root->groups[n].group->opts == cfg)
- return &root->groups[n];
+ for (int n = 0; n < shadow->num_groups; n++) {
+ if (shadow->groups[n].group->opts == cfg)
+ return &shadow->groups[n];
}
return NULL;
@@ -509,18 +528,20 @@ static void add_sub_group(struct m_config *config, const char *name_prefix,
int parent_group_index, int parent_ptr,
const struct m_sub_options *subopts)
{
- // Can't be used multiple times.
- for (int n = 0; n < config->num_groups; n++)
- assert(config->groups[n].group != subopts);
+ struct m_config_shadow *shadow = config->shadow;
+
+ // Can't be used multiple times.
+ for (int n = 0; n < shadow->num_groups; n++)
+ assert(shadow->groups[n].group != subopts);
// You can only use UPDATE_ flags here.
assert(!(subopts->change_flags & ~(unsigned)UPDATE_OPTS_MASK));
- assert(parent_group_index >= -1 && parent_group_index < config->num_groups);
+ assert(parent_group_index >= -1 && parent_group_index < shadow->num_groups);
- int group_index = config->num_groups++;
- MP_TARRAY_GROW(config, config->groups, group_index);
- config->groups[group_index] = (struct m_config_group){
+ int group_index = shadow->num_groups++;
+ MP_TARRAY_GROW(shadow, shadow->groups, group_index);
+ shadow->groups[group_index] = (struct m_config_group){
.group = subopts,
.parent_group = parent_group_index,
.parent_ptr = parent_ptr,
@@ -547,7 +568,7 @@ static void add_sub_group(struct m_config *config, const char *name_prefix,
MP_TARRAY_APPEND(config, config->opts, config->num_opts, co);
}
- config->groups[group_index].co_end_index = config->num_opts;
+ shadow->groups[group_index].co_end_index = config->num_opts;
// Initialize sub-structs. These have to come after, because co_index and
// co_end_index must strictly be for a single struct only.
@@ -571,7 +592,7 @@ static void add_sub_group(struct m_config *config, const char *name_prefix,
}
}
- config->groups[group_index].group_count = config->num_groups - group_index;
+ shadow->groups[group_index].group_count = shadow->num_groups - group_index;
}
struct m_config_option *m_config_get_co_raw(const struct m_config *config,
@@ -665,7 +686,9 @@ const void *m_config_get_co_default(const struct m_config *config,
if (co->opt->defval)
return co->opt->defval;
- const struct m_sub_options *subopt = config->groups[co->group_index].group;
+ const struct m_sub_options *subopt =
+ config->shadow->groups[co->group_index].group;
+
if (co->opt->offset >= 0 && subopt->defaults)
return (char *)subopt->defaults + co->opt->offset;
@@ -1227,13 +1250,7 @@ struct mpv_node m_config_get_profiles(struct m_config *config)
void m_config_create_shadow(struct m_config *config)
{
assert(config->global);
- assert(!config->shadow && !config->global->config);
-
- config->shadow = talloc_zero(NULL, struct m_config_shadow);
- config->shadow->data =
- allocate_option_data(config->shadow, config, 0, config->data);
- config->shadow->root = config;
- pthread_mutex_init(&config->shadow->lock, NULL);
+ assert(!config->global->config);
config->global->config = config->shadow;
}
@@ -1253,12 +1270,11 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
const struct m_sub_options *group)
{
struct m_config_shadow *shadow = global->config;
- struct m_config *root = shadow->root;
int group_index = -1;
- for (int n = 0; n < root->num_groups; n++) {
+ for (int n = 0; n < shadow->num_groups; n++) {
// group==NULL is special cased to root group.
- if (root->groups[n].group == group || (!group && !n)) {
+ if (shadow->groups[n].group == group || (!group && !n)) {
group_index = n;
break;
}
@@ -1271,7 +1287,8 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
cache->shadow = shadow;
pthread_mutex_lock(&shadow->lock);
- cache->data = allocate_option_data(cache, root, group_index, shadow->data);
+ cache->data =
+ allocate_option_data(cache, shadow->root, group_index, shadow->data);
pthread_mutex_unlock(&shadow->lock);
cache->opts = cache->data->gdata[0].udata;
@@ -1282,6 +1299,7 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
static bool update_options(struct m_config_data *dst, struct m_config_data *src)
{
assert(dst->root == src->root);
+ assert(dst->shadow == src->shadow);
bool res = false;
dst->ts = src->ts;
@@ -1290,9 +1308,9 @@ static bool update_options(struct m_config_data *dst, struct m_config_data *src)
int group_s = MPMAX(dst->group_index, src->group_index);
int group_e = MPMIN(dst->group_index + dst->num_gdata,
src->group_index + src->num_gdata);
- assert(group_s >= 0 && group_e <= dst->root->num_groups);
+ assert(group_s >= 0 && group_e <= dst->shadow->num_groups);
for (int n = group_s; n < group_e; n++) {
- struct m_config_group *g = &dst->root->groups[n];
+ struct m_config_group *g = &dst->shadow->groups[n];
struct m_group_data *gsrc = m_config_gdata(src, n);
struct m_group_data *gdst = m_config_gdata(dst, n);
assert(gsrc && gdst);
@@ -1359,7 +1377,7 @@ void m_config_notify_change_co(struct m_config *config,
int changed = co->opt->flags & UPDATE_OPTS_MASK;
int group_index = co->group_index;
while (group_index >= 0) {
- struct m_config_group *g = &config->groups[group_index];
+ struct m_config_group *g = &shadow->groups[group_index];
changed |= g->group->change_flags;
group_index = g->parent_group;
}
diff --git a/options/m_config.h b/options/m_config.h
index a640f43eef..207870e12a 100644
--- a/options/m_config.h
+++ b/options/m_config.h
@@ -87,13 +87,6 @@ typedef struct m_config {
void *optstruct; // struct mpopts or other
- // Private. List of m_sub_options instances.
- // Index 0 is the top-level and is always present.
- // Immutable after init.
- // Invariant: a parent is always at a lower index than any of its children.
- struct m_config_group *groups;
- int num_groups;
-
// Private. Non-NULL if data was allocated. m_config_option.data uses it.
struct m_config_data *data;