From 50177aaa3b2040cc76d59b2e19687d9016641c39 Mon Sep 17 00:00:00 2001 From: wm4 Date: Thu, 5 Mar 2020 21:05:14 +0100 Subject: dispatch: add strange mechanism for making worker threads responsive This is probably a sin for the sake of user experience. See a following commit that wires up f_decoder_wrapper with it. --- misc/dispatch.c | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) (limited to 'misc/dispatch.c') diff --git a/misc/dispatch.c b/misc/dispatch.c index 1102c564ae..0c3c574afa 100644 --- a/misc/dispatch.c +++ b/misc/dispatch.c @@ -30,6 +30,8 @@ struct mp_dispatch_queue { pthread_cond_t cond; void (*wakeup_fn)(void *wakeup_ctx); void *wakeup_ctx; + void (*onlock_fn)(void *onlock_ctx); + void *onlock_ctx; // Time at which mp_dispatch_queue_process() should return. int64_t wait; // Make mp_dispatch_queue_process() exit if it's idle. @@ -94,8 +96,9 @@ struct mp_dispatch_queue *mp_dispatch_create(void *ta_parent) // the wakeup_fn could for example write a byte into a "wakeup" pipe in order // to unblock the select(). The wakeup_fn is called from the dispatch queue // when there are new dispatch items, and the target thread should then enter -// mp_dispatch_queue_process() as soon as possible. Note that wakeup_fn is -// called under no lock, so you might have to do synchronization yourself. +// mp_dispatch_queue_process() as soon as possible. +// Note that this setter does not do internal synchronization, so you must set +// it before other threads see it. void mp_dispatch_set_wakeup_fn(struct mp_dispatch_queue *queue, void (*wakeup_fn)(void *wakeup_ctx), void *wakeup_ctx) @@ -104,6 +107,22 @@ void mp_dispatch_set_wakeup_fn(struct mp_dispatch_queue *queue, queue->wakeup_ctx = wakeup_ctx; } +// Set a function that will be called by mp_dispatch_lock() if the target thread +// is not calling mp_dispatch_queue_process() right now. This is an obscure, +// optional mechanism to make a worker thread react to external events more +// quickly. The idea is that the callback will make the worker thread to stop +// doing whatever (e.g. by setting a flag), and call mp_dispatch_queue_process() +// in order to let mp_dispatch_lock() calls continue sooner. +// Like wakeup_fn, this setter does no internal synchronization, and you must +// not access the dispatch queue itself from the callback. +void mp_dispatch_set_onlock_fn(struct mp_dispatch_queue *queue, + void (*onlock_fn)(void *onlock_ctx), + void *onlock_ctx) +{ + queue->onlock_fn = onlock_fn; + queue->onlock_ctx = onlock_ctx; +} + static void mp_dispatch_append(struct mp_dispatch_queue *queue, struct mp_dispatch_item *item) { @@ -356,6 +375,8 @@ void mp_dispatch_lock(struct mp_dispatch_queue *queue) // And now wait until the target thread gets "trapped" within the // mp_dispatch_queue_process() call, which will mean we get exclusive // access to the target's thread state. + if (queue->onlock_fn) + queue->onlock_fn(queue->onlock_ctx); while (!queue->in_process) { pthread_mutex_unlock(&queue->lock); if (queue->wakeup_fn) -- cgit v1.2.3