summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2014-04-23 20:45:10 +0200
committerwm4 <wm4@nowhere>2014-04-23 21:16:52 +0200
commit80ff94131b477ad9156f1c68da7b8588544fee33 (patch)
treea98ba8c3f4bcf96fc5ba0eb7c7de57a1ab87ab64
parent29b726039821ff3f0435644c791412ed8a75319a (diff)
downloadmpv-80ff94131b477ad9156f1c68da7b8588544fee33.tar.bz2
mpv-80ff94131b477ad9156f1c68da7b8588544fee33.tar.xz
dispatch: implement timeout
Note that this mechanism is similarly "unreliable" as for example pthread_cond_timedwait(). Trying to target the exact wait time will just make it more complex. The main use case for this is for threads which either use the dispatch centrally and want mp_dispatch_queue_process to do a blocking wait for new work, or threads which have to implement timers. For the former, anything is fine, as long as they don't have to do active waiting for new works. For the former, callers are better off recalculating their deadline after every call.
-rw-r--r--misc/dispatch.c17
1 files changed, 11 insertions, 6 deletions
diff --git a/misc/dispatch.c b/misc/dispatch.c
index 53d1829e88..4a5972aff2 100644
--- a/misc/dispatch.c
+++ b/misc/dispatch.c
@@ -163,17 +163,17 @@ void mp_dispatch_run(struct mp_dispatch_queue *queue,
// Process any outstanding dispatch items in the queue. This also handles
// suspending or locking the target thread.
-// The timeout specifies the maximum wait time, but the actual time spent in
-// this function can be much higher if the suspending/locking functions are
-// used, or if executing the dispatch items takes time.
-// TODO: implement timeout
+// The timeout specifies the minimum wait time. The actual time spent in this
+// function can be much higher if the suspending/locking functions are used, or
+// if executing the dispatch items takes time. On the other hand, this function
+// can return much earlier than the timeout due to sporadic wakeups.
void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
{
pthread_mutex_lock(&queue->lock);
queue->suspended = true;
// Wake up thread which called mp_dispatch_suspend().
pthread_cond_broadcast(&queue->cond);
- while (queue->head || queue->suspend_requested) {
+ while (queue->head || queue->suspend_requested || timeout > 0) {
if (queue->head) {
struct mp_dispatch_item *item = queue->head;
queue->head = item->next;
@@ -197,8 +197,13 @@ void mp_dispatch_queue_process(struct mp_dispatch_queue *queue, double timeout)
pthread_cond_broadcast(&queue->cond);
}
} else {
- pthread_cond_wait(&queue->cond, &queue->lock);
+ if (timeout > 0) {
+ mpthread_cond_timed_wait(&queue->cond, &queue->lock, timeout);
+ } else {
+ pthread_cond_wait(&queue->cond, &queue->lock);
+ }
}
+ timeout = 0;
}
queue->suspended = false;
pthread_mutex_unlock(&queue->lock);