From 29a51900c6047798244afaca271618caeeeeeee8 Mon Sep 17 00:00:00 2001 From: wm4 Date: Sat, 19 May 2018 17:06:00 +0200 Subject: player: some further cleanup of the mp_cancel crap Alway give each demuxer its own mp_cancel instance. This makes management of the mp_cancel things much easier. Also, instead of having add/remove functions for mp_cancel slaves, replace them with a simpler to use set_parent function. Remove cancel_and_free_demuxer(), which had mpctx as parameter only to check an assumption. With this commit, demuxers have their own mp_cancel, so add demux_cancel_and_free() which makes use of it. --- misc/thread_tools.c | 39 +++++++++++++++++---------------------- misc/thread_tools.h | 14 ++++++-------- 2 files changed, 23 insertions(+), 30 deletions(-) (limited to 'misc') diff --git a/misc/thread_tools.c b/misc/thread_tools.c index ecf6bc2381..91b774eb93 100644 --- a/misc/thread_tools.c +++ b/misc/thread_tools.c @@ -105,12 +105,7 @@ static void cancel_destroy(void *p) assert(!c->slaves.head); // API user error - // We can access c->parent without synchronization, because: - // - since c is being destroyed, nobody can explicitly remove it as slave - // at the same time - // - c->parent needs to stay valid as long as the slave exists - if (c->parent) - mp_cancel_remove_slave(c->parent, c); + mp_cancel_set_parent(c, NULL); if (c->wakeup_pipe[0] >= 0) { close(c->wakeup_pipe[0]); @@ -225,25 +220,25 @@ void mp_cancel_set_cb(struct mp_cancel *c, void (*cb)(void *ctx), void *ctx) pthread_mutex_unlock(&c->lock); } -void mp_cancel_add_slave(struct mp_cancel *c, struct mp_cancel *slave) -{ - pthread_mutex_lock(&c->lock); - assert(!slave->parent); - slave->parent = c; - LL_APPEND(siblings, &c->slaves, slave); - retrigger_locked(c); - pthread_mutex_unlock(&c->lock); -} - -void mp_cancel_remove_slave(struct mp_cancel *c, struct mp_cancel *slave) +void mp_cancel_set_parent(struct mp_cancel *slave, struct mp_cancel *parent) { - pthread_mutex_lock(&c->lock); + // We can access c->parent without synchronization, because: + // - concurrent mp_cancel_set_parent() calls to slave are not allowed + // - slave->parent needs to stay valid as long as the slave exists + if (slave->parent == parent) + return; if (slave->parent) { - assert(slave->parent == c); - slave->parent = NULL; - LL_REMOVE(siblings, &c->slaves, slave); + pthread_mutex_lock(&slave->parent->lock); + LL_REMOVE(siblings, &slave->parent->slaves, slave); + pthread_mutex_unlock(&slave->parent->lock); + } + slave->parent = parent; + if (slave->parent) { + pthread_mutex_lock(&slave->parent->lock); + LL_APPEND(siblings, &slave->parent->slaves, slave); + retrigger_locked(slave->parent); + pthread_mutex_unlock(&slave->parent->lock); } - pthread_mutex_unlock(&c->lock); } int mp_cancel_get_fd(struct mp_cancel *c) diff --git a/misc/thread_tools.h b/misc/thread_tools.h index 2198181e6c..89d84ce0b6 100644 --- a/misc/thread_tools.h +++ b/misc/thread_tools.h @@ -67,14 +67,12 @@ void mp_cancel_reset(struct mp_cancel *c); // There is only one callback. Create a slave mp_cancel to get a private one. void mp_cancel_set_cb(struct mp_cancel *c, void (*cb)(void *ctx), void *ctx); -// If c gets triggered, automatically trigger slave. Trying to add a slave more -// than once or to multiple parents is undefined behavior. -// The parent mp_cancel must remain valid until the slave is manually removed -// or destroyed. Destroying a mp_cancel that still has slaves is an error. -void mp_cancel_add_slave(struct mp_cancel *c, struct mp_cancel *slave); - -// Undo mp_cancel_add_slave(). Ignores never added slaves for easier cleanup. -void mp_cancel_remove_slave(struct mp_cancel *c, struct mp_cancel *slave); +// If parent gets triggered, automatically trigger slave. There is only 1 +// parent; setting NULL clears the parent. Freeing slave also automatically +// ends the parent link, but the parent mp_cancel must remain valid until the +// slave is manually removed or destroyed. Destroying a mp_cancel that still +// has slaves is an error. +void mp_cancel_set_parent(struct mp_cancel *slave, struct mp_cancel *parent); // win32 "Event" HANDLE that indicates the current mp_cancel state. void *mp_cancel_get_event(struct mp_cancel *c); -- cgit v1.2.3