From 0656411e97afd5710b02563ee0b28423443592e9 Mon Sep 17 00:00:00 2001 From: wm4 Date: Wed, 31 Jul 2013 20:44:16 +0200 Subject: m_config: store file local backup options differently File local options need to backup the global option value while a file is played. Instead of keeping a pointer in m_config_option for the backup value, put it into a separate list. This reduces per-option overhead for a rarely used obscure feature. (This implementation would have been a bit dumb in pre-mpv m_config, because there local options were the default, and _all_ options were backed up when starting playback of a file. This is not the case anymore, and normally only a very small number of options are backed up by default.) --- core/m_config.c | 43 +++++++++++++++++++++++++++++-------------- core/m_config.h | 4 ++-- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/core/m_config.c b/core/m_config.c index 414d397049..7faca24497 100644 --- a/core/m_config.c +++ b/core/m_config.c @@ -47,6 +47,13 @@ struct m_profile { char **opts; }; +// In the file local case, this contains the old global value. +struct m_opt_backup { + struct m_opt_backup *next; + struct m_config_option *co; + void *backup; +}; + static int parse_include(struct m_config *config, struct bstr param, bool set) { if (param.len == 0) @@ -175,14 +182,14 @@ static void add_options(struct m_config *config, static int config_destroy(void *p) { struct m_config *config = p; + if (config->file_local_mode) + m_config_leave_file_local(config); for (struct m_config_option *copt = config->opts; copt; copt = copt->next) { if (copt->alias_owner) continue; if (copt->opt->type->flags & M_OPT_TYPE_DYNAMIC) { m_option_free(copt->opt, copt->data); } - if (copt->global_backup) - m_option_free(copt->opt, copt->global_backup); } return 0; } @@ -246,18 +253,26 @@ int m_config_initialize_obj(struct m_config *config, struct m_obj_desc *desc, static void ensure_backup(struct m_config *config, struct m_config_option *co) { - while (co->alias_owner) - co = co->alias_owner; if (!config->file_local_mode) return; if (co->opt->type->flags & M_OPT_TYPE_HAS_CHILD) return; if (co->opt->flags & M_OPT_GLOBAL) return; - if (co->global_backup) + if (!co->data) return; - co->global_backup = talloc_zero_size(co, co->opt->type->size); - m_option_copy(co->opt, co->global_backup, co->data); + for (struct m_opt_backup *cur = config->backup_opts; cur; cur = cur->next) { + if (cur->co->data == co->data) // comparing data ptr catches aliases + return; + } + struct m_opt_backup *bc = talloc_ptrtype(NULL, bc); + *bc = (struct m_opt_backup) { + .co = co, + .backup = talloc_zero_size(bc, co->opt->type->size), + }; + m_option_copy(co->opt, bc->backup, co->data); + bc->next = config->backup_opts; + config->backup_opts = bc; } void m_config_enter_file_local(struct m_config *config) @@ -274,13 +289,13 @@ void m_config_leave_file_local(struct m_config *config) { assert(config->file_local_mode); config->file_local_mode = false; - for (struct m_config_option *co = config->opts; co; co = co->next) { - if (co->global_backup) { - m_option_copy(co->opt, co->data, co->global_backup); - m_option_free(co->opt, co->global_backup); - talloc_free(co->global_backup); - co->global_backup = NULL; - } + while (config->backup_opts) { + struct m_opt_backup *bc = config->backup_opts; + config->backup_opts = bc->next; + + m_option_copy(bc->co->opt, bc->co->data, bc->backup); + m_option_free(bc->co->opt, bc->backup); + talloc_free(bc); } } diff --git a/core/m_config.h b/core/m_config.h index c48a4f1281..1ee7ecf1c0 100644 --- a/core/m_config.h +++ b/core/m_config.h @@ -44,8 +44,6 @@ struct m_config_option { const struct m_option *opt; // Raw value of the option. void *data; - // Raw value of the backup of the global value (or NULL). - void *global_backup; // If this is a suboption, the option that contains this option. struct m_config_option *parent; // If this option aliases another, more important option. The alias_owner @@ -70,6 +68,8 @@ typedef struct m_config { // Depth when recursively including profiles. int profile_depth; + struct m_opt_backup *backup_opts; + bool use_profiles; int (*includefunc)(struct m_config *conf, char *filename); -- cgit v1.2.3