diff options
author | wm4 <wm4@nowhere> | 2018-05-17 20:58:49 +0200 |
---|---|---|
committer | wm4 <wm4@nowhere> | 2018-05-24 19:56:35 +0200 |
commit | 31b78ad7fa97d8047b609c1647a273e72612d425 (patch) | |
tree | d6a5e960ac431eef46d01b440fd504b1ac1f1159 /misc/thread_tools.c | |
parent | 12bd4fe9abce797a3c98dc437579b163e0a8162a (diff) | |
download | mpv-31b78ad7fa97d8047b609c1647a273e72612d425.tar.bz2 mpv-31b78ad7fa97d8047b609c1647a273e72612d425.tar.xz |
misc: move mp_cancel from stream.c to thread_tools.c
It seems a bit inappropriate to have dumped this into stream.c, even if
it's roughly speaking its main user. At least it made its way somewhat
unfortunately to other components not related to the stream or demuxer
layer at all.
I'm too greedy to give this weird helper its own file, so dump it into
thread_tools.c.
Probably a somewhat pointless change.
Diffstat (limited to 'misc/thread_tools.c')
-rw-r--r-- | misc/thread_tools.c | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/misc/thread_tools.c b/misc/thread_tools.c index 4bcb952267..57a4900ad6 100644 --- a/misc/thread_tools.c +++ b/misc/thread_tools.c @@ -15,6 +15,19 @@ #include <assert.h> #include <string.h> +#include <sys/types.h> +#include <unistd.h> +#include <errno.h> + +#ifdef __MINGW32__ +#include <windows.h> +#else +#include <poll.h> +#endif + +#include "common/common.h" +#include "osdep/atomic.h" +#include "osdep/io.h" #include "thread_tools.h" @@ -60,3 +73,120 @@ bool mp_waiter_poll(struct mp_waiter *waiter) pthread_mutex_unlock(&waiter->lock); return r; } + +#ifndef __MINGW32__ +struct mp_cancel { + atomic_bool triggered; + int wakeup_pipe[2]; +}; + +static void cancel_destroy(void *p) +{ + struct mp_cancel *c = p; + if (c->wakeup_pipe[0] >= 0) { + close(c->wakeup_pipe[0]); + close(c->wakeup_pipe[1]); + } +} + +struct mp_cancel *mp_cancel_new(void *talloc_ctx) +{ + struct mp_cancel *c = talloc_ptrtype(talloc_ctx, c); + talloc_set_destructor(c, cancel_destroy); + *c = (struct mp_cancel){.triggered = ATOMIC_VAR_INIT(false)}; + mp_make_wakeup_pipe(c->wakeup_pipe); + return c; +} + +void mp_cancel_trigger(struct mp_cancel *c) +{ + atomic_store(&c->triggered, true); + (void)write(c->wakeup_pipe[1], &(char){0}, 1); +} + +void mp_cancel_reset(struct mp_cancel *c) +{ + atomic_store(&c->triggered, false); + // Flush it fully. + while (1) { + int r = read(c->wakeup_pipe[0], &(char[256]){0}, 256); + if (r < 0 && errno == EINTR) + continue; + if (r <= 0) + break; + } +} + +bool mp_cancel_test(struct mp_cancel *c) +{ + return c ? atomic_load_explicit(&c->triggered, memory_order_relaxed) : false; +} + +bool mp_cancel_wait(struct mp_cancel *c, double timeout) +{ + struct pollfd fd = { .fd = c->wakeup_pipe[0], .events = POLLIN }; + poll(&fd, 1, timeout * 1000); + return fd.revents & POLLIN; +} + +int mp_cancel_get_fd(struct mp_cancel *c) +{ + return c->wakeup_pipe[0]; +} + +#else + +struct mp_cancel { + atomic_bool triggered; + HANDLE event; +}; + +static void cancel_destroy(void *p) +{ + struct mp_cancel *c = p; + CloseHandle(c->event); +} + +struct mp_cancel *mp_cancel_new(void *talloc_ctx) +{ + struct mp_cancel *c = talloc_ptrtype(talloc_ctx, c); + talloc_set_destructor(c, cancel_destroy); + *c = (struct mp_cancel){.triggered = ATOMIC_VAR_INIT(false)}; + c->event = CreateEventW(NULL, TRUE, FALSE, NULL); + return c; +} + +void mp_cancel_trigger(struct mp_cancel *c) +{ + atomic_store(&c->triggered, true); + SetEvent(c->event); +} + +void mp_cancel_reset(struct mp_cancel *c) +{ + atomic_store(&c->triggered, false); + ResetEvent(c->event); +} + +bool mp_cancel_test(struct mp_cancel *c) +{ + return c ? atomic_load_explicit(&c->triggered, memory_order_relaxed) : false; +} + +bool mp_cancel_wait(struct mp_cancel *c, double timeout) +{ + return WaitForSingleObject(c->event, timeout < 0 ? INFINITE : timeout * 1000) + == WAIT_OBJECT_0; +} + +void *mp_cancel_get_event(struct mp_cancel *c) +{ + return c->event; +} + +int mp_cancel_get_fd(struct mp_cancel *c) +{ + return -1; +} + +#endif |