summaryrefslogtreecommitdiffstats
path: root/options/m_config.h
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2017-08-22 15:50:33 +0200
committerwm4 <wm4@nowhere>2017-08-22 15:50:33 +0200
commitd2bdb72b69536370c3046107fc593896e74803c3 (patch)
tree09d5913f981ee5f5e0d43fbfd24b06f67eb8dd5e /options/m_config.h
parent5361c0b5d897ec7c969d2a75bb2dde345d62a59c (diff)
downloadmpv-d2bdb72b69536370c3046107fc593896e74803c3.tar.bz2
mpv-d2bdb72b69536370c3046107fc593896e74803c3.tar.xz
options: add a thread-safe way to notify option updates
So far, we had a thread-safe way to read options, but no option update notification mechanism. Everything was funneled though the main thread's central mp_option_change_callback() function. For example, if the panscan options were changed, the function called vo_control() with VOCTRL_SET_PANSCAN to manually notify the VO thread of updates. This worked, but's pretty inconvenient. Most of these problems come from the fact that MPlayer was written as a single-threaded program. This commit works towards a more flexible mechanism. It adds an update callback to m_config_cache (the thing that is already used for thread-safe access of global options). This alone would still be rather inconvenient, at least in context of VOs. Add another mechanism on top of it that uses mp_dispatch_queue, and takes care of some annoying synchronization issues. We extend mp_dispatch_queue itself to make this easier and slightly more efficient. As a first application, use this to reimplement certain VO scaling and renderer options. The update_opts() function translates these to the "old" VOCTRLs, though. An annoyingly subtle issue is that m_config_cache's destructor now releases pending notifications, and must be released before the associated dispatch queue. Otherwise, it could happen that option updates during e.g. VO destruction queue or run stale entries, which is not expected. Rather untested. The singly-linked list code in dispatch.c is probably buggy, and I bet some aspects about synchronization are not entirely sane.
Diffstat (limited to 'options/m_config.h')
-rw-r--r--options/m_config.h31
1 files changed, 29 insertions, 2 deletions
diff --git a/options/m_config.h b/options/m_config.h
index 65145c093b..fc32ca5bf0 100644
--- a/options/m_config.h
+++ b/options/m_config.h
@@ -275,9 +275,20 @@ struct m_config_cache {
struct m_config *shadow_config;
long long ts;
int group;
+ bool in_list;
+ // --- Implicitly synchronized by setting/unsetting wakeup_cb.
+ struct mp_dispatch_queue *wakeup_dispatch_queue;
+ void (*wakeup_dispatch_cb)(void *ctx);
+ void *wakeup_dispatch_cb_ctx;
+ // --- Protected by shadow->lock
+ void (*wakeup_cb)(void *ctx);
+ void *wakeup_cb_ctx;
};
// Create a mirror copy from the global options.
+// Keep in mind that a m_config_cache object is not thread-safe; it merely
+// provides thread-safe access to the global options. All API functions for
+// the same m_config_cache object must synchronized, unless otherwise noted.
// ta_parent: parent for the returned allocation
// global: option data source
// group: the option group to return. This can be NULL for the global option
@@ -287,6 +298,22 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
struct mpv_global *global,
const struct m_sub_options *group);
+// If any of the options in the group possibly changes, call this callback. The
+// callback must not actually access the cache or anything option related.
+// Instead, it must wake up the thread that normally accesses the cache.
+void m_config_cache_set_wakeup_cb(struct m_config_cache *cache,
+ void (*cb)(void *ctx), void *cb_ctx);
+
+// If any of the options in the group change, call this callback on the given
+// dispatch queue. This is higher level than m_config_cache_set_wakeup_cb(),
+// and you can do anything you want in the callback (assuming the dispatch
+// queue is processed in the same thread that accesses m_config_cache API).
+// To ensure clean shutdown, you must destroy the m_config_cache (or unset the
+// callback) before the dispatch queue is destroyed.
+void m_config_cache_set_dispatch_change_cb(struct m_config_cache *cache,
+ struct mp_dispatch_queue *dispatch,
+ void (*cb)(void *ctx), void *cb_ctx);
+
// Update the options in cache->opts to current global values. Return whether
// there was an update notification at all (which may or may not indicate that
// some options have changed).
@@ -295,13 +322,13 @@ struct m_config_cache *m_config_cache_alloc(void *ta_parent,
bool m_config_cache_update(struct m_config_cache *cache);
// Like m_config_cache_alloc(), but return the struct (m_config_cache->opts)
-// directly, with no way to update the config.
+// directly, with no way to update the config. Basically this returns a copy
+// with a snapshot of the current option values.
// Warning: does currently not set the child as its own talloc root, which
// means the only way to free the struct is by freeing ta_parent.
void *mp_get_config_group(void *ta_parent, struct mpv_global *global,
const struct m_sub_options *group);
-
// Read a single global option in a thread-safe way. For multiple options,
// use m_config_cache. The option must exist and match the provided type (the
// type is used as a sanity check only). Performs semi-expensive lookup.