summaryrefslogtreecommitdiffstats
path: root/options/m_config_core.c
diff options
context:
space:
mode:
authorDudemanguy <random342@airmail.cc>2024-04-22 17:52:02 -0500
committerDudemanguy <random342@airmail.cc>2024-04-26 17:42:52 +0000
commit76367dae35ef4253e99205ccccf1dbccfc70bdfc (patch)
tree03e8aa1000ca1d6d8e42098ad94aef65c37769cb /options/m_config_core.c
parent2e03e0305caf851e305a7d73af1efe4a4fdf693a (diff)
downloadmpv-76367dae35ef4253e99205ccccf1dbccfc70bdfc.tar.bz2
mpv-76367dae35ef4253e99205ccccf1dbccfc70bdfc.tar.xz
m_config_core: fix forced option notification with m_config_cache
bc28f7693d095758275448410aaa91255482857a originally added this, but the implementation isn't correct and causes excessive notifications when writing to other options which may have bad behavior in some some circumstances. Fix this by reworking the implementation for force options so that the timestamps of the option update compared instead. Whenever an option gets changed, the internal timestamp in the cache is always incremented. For a special force option, we can save this timestamp internally as well. Because cache_check_update is always checked before potentially sending an option notification, we know that if the internal timestamp is equal to the timestamp saved by a force update option, it must have been previously written. Thus, the notification can be sent. This lets options like geometry work repeatedly but without constantly sending notifications. Fixes #13954.
Diffstat (limited to 'options/m_config_core.c')
-rw-r--r--options/m_config_core.c54
1 files changed, 31 insertions, 23 deletions
diff --git a/options/m_config_core.c b/options/m_config_core.c
index 0cd51ceb41..328ec6479f 100644
--- a/options/m_config_core.c
+++ b/options/m_config_core.c
@@ -99,12 +99,17 @@ struct config_cache {
void *wakeup_cb_ctx;
};
+struct force_update {
+ char *name;
+ uint64_t ts;
+};
+
// Per m_config_data state for each m_config_group.
struct m_group_data {
- char *udata; // pointer to group user option struct
- uint64_t ts; // timestamp of the data copy
- char **force_updates; // track if any opt in group was written with force_update
- int force_updates_len;
+ char *udata; // pointer to group user option struct
+ uint64_t ts; // timestamp of the data copy
+ struct force_update **force_update; // tracks opts that are written with force update
+ int force_update_len;
};
static void add_sub_group(struct m_config_shadow *shadow, const char *name_prefix,
@@ -590,23 +595,30 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
return m_config_cache_from_shadow(ta_parent, global->config, group);
}
-static void clear_force_update_list(struct m_group_data *gsrc)
+static void append_force_update(struct m_config_cache *cache, struct m_group_data *gdata,
+ const char *opt_name)
{
- int index = 0;
- while (index < gsrc->force_updates_len) {
- TA_FREEP(&gsrc->force_updates[index]);
- ++index;
+ for (int i = 0; i < gdata->force_update_len; ++i) {
+ if (strcmp(opt_name, gdata->force_update[i]->name) == 0) {
+ gdata->force_update[i]->ts = gdata->ts;
+ return;
+ }
}
- gsrc->force_updates_len = 0;
+ struct force_update *new_update = talloc_zero(cache, struct force_update);
+ new_update->name = talloc_strdup(cache, opt_name);
+ new_update->ts = gdata->ts;
+ MP_TARRAY_APPEND(cache, gdata->force_update, gdata->force_update_len, new_update);
}
-static bool check_force_update_list(struct m_group_data *gsrc, const char *opt_name)
+static bool check_force_update(struct m_group_data *gdata, const char *opt_name,
+ uint64_t timestamp)
{
- int index = 0;
- while (index < gsrc->force_updates_len) {
- if (strcmp(opt_name, gsrc->force_updates[index]) == 0)
+ for (int i = 0; i < gdata->force_update_len; ++i) {
+ if ((strcmp(opt_name, gdata->force_update[i]->name) == 0) &&
+ gdata->force_update[i]->ts == timestamp)
+ {
return true;
- ++index;
+ }
}
return false;
}
@@ -637,8 +649,8 @@ static void update_next_option(struct m_config_cache *cache, void **p_opt)
if (opt->offset >= 0 && opt->type->size) {
bool opt_equal = m_option_equal(opt, ddst, dsrc);
- bool force_update = opt->force_update && gsrc->force_updates_len &&
- check_force_update_list(gsrc, opt->name);
+ bool force_update = opt->force_update &&
+ check_force_update(gsrc, opt->name, in->ts);
if (!opt_equal || force_update) {
uint64_t ch = get_opt_change_mask(dst->shadow,
in->upd_group, dst->group_index, opt);
@@ -666,8 +678,6 @@ static void update_next_option(struct m_config_cache *cache, void **p_opt)
}
gdst->ts = gsrc->ts;
- } else {
- clear_force_update_list(gsrc);
}
in->upd_group++;
@@ -791,10 +801,8 @@ bool m_config_cache_write_opt(struct m_config_cache *cache, void *ptr)
}
}
- if (opt->force_update) {
- MP_TARRAY_APPEND(shadow, gsrc->force_updates, gsrc->force_updates_len,
- talloc_strdup(shadow, opt->name));
- }
+ if (opt->force_update)
+ append_force_update(cache, gsrc, opt->name);
mp_mutex_unlock(&shadow->lock);