diff options
-rw-r--r-- | demux/demux.c | 1 | ||||
-rw-r--r-- | demux/demux_lavf.c | 1 | ||||
-rw-r--r-- | demux/demux_mkv_timeline.c | 1 | ||||
-rw-r--r-- | demux/demux_playlist.c | 1 | ||||
-rw-r--r-- | misc/thread_tools.c | 130 | ||||
-rw-r--r-- | misc/thread_tools.h | 28 | ||||
-rw-r--r-- | osdep/subprocess-posix.c | 3 | ||||
-rw-r--r-- | osdep/subprocess-win.c | 1 | ||||
-rw-r--r-- | player/main.c | 2 | ||||
-rw-r--r-- | stream/cache.c | 1 | ||||
-rw-r--r-- | stream/stream.c | 136 | ||||
-rw-r--r-- | stream/stream.h | 8 | ||||
-rw-r--r-- | stream/stream_file.c | 1 | ||||
-rw-r--r-- | stream/stream_lavf.c | 1 | ||||
-rw-r--r-- | stream/stream_libarchive.c | 1 |
15 files changed, 171 insertions, 145 deletions
diff --git a/demux/demux.c b/demux/demux.c index f386c3c2ae..0edfaa95bf 100644 --- a/demux/demux.c +++ b/demux/demux.c @@ -34,6 +34,7 @@ #include "mpv_talloc.h" #include "common/msg.h" #include "common/global.h" +#include "misc/thread_tools.h" #include "osdep/atomic.h" #include "osdep/threads.h" diff --git a/demux/demux_lavf.c b/demux/demux_lavf.c index 60ae878398..a0b5ff7472 100644 --- a/demux/demux_lavf.c +++ b/demux/demux_lavf.c @@ -42,6 +42,7 @@ #include "common/av_common.h" #include "misc/bstr.h" #include "misc/charset_conv.h" +#include "misc/thread_tools.h" #include "stream/stream.h" #include "demux.h" diff --git a/demux/demux_mkv_timeline.c b/demux/demux_mkv_timeline.c index 3ad24eb8a5..277ff9c1ee 100644 --- a/demux/demux_mkv_timeline.c +++ b/demux/demux_mkv_timeline.c @@ -39,6 +39,7 @@ #include "options/options.h" #include "options/path.h" #include "misc/bstr.h" +#include "misc/thread_tools.h" #include "common/common.h" #include "common/playlist.h" #include "stream/stream.h" diff --git a/demux/demux_playlist.c b/demux/demux_playlist.c index 3a65ada451..0aa542534d 100644 --- a/demux/demux_playlist.c +++ b/demux/demux_playlist.c @@ -25,6 +25,7 @@ #include "options/options.h" #include "common/msg.h" #include "common/playlist.h" +#include "misc/thread_tools.h" #include "options/path.h" #include "stream/stream.h" #include "osdep/io.h" 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 diff --git a/misc/thread_tools.h b/misc/thread_tools.h index 54f396dead..a734ac85b0 100644 --- a/misc/thread_tools.h +++ b/misc/thread_tools.h @@ -37,3 +37,31 @@ void mp_waiter_wakeup(struct mp_waiter *waiter, uintptr_t value); // wakeup (in parallel to mp_waiter). // You still need to call mp_waiter_wait() to free resources. bool mp_waiter_poll(struct mp_waiter *waiter); + +// Basically a binary semaphore that supports signaling the semaphore value to +// a bunch of other complicated mechanisms (such as wakeup pipes). It was made +// for aborting I/O and thus has according naming. +struct mp_cancel; + +struct mp_cancel *mp_cancel_new(void *talloc_ctx); + +// Request abort. +void mp_cancel_trigger(struct mp_cancel *c); + +// Return whether the caller should abort. +// For convenience, c==NULL is allowed. +bool mp_cancel_test(struct mp_cancel *c); + +// Wait until the even is signaled. If the timeout (in seconds) expires, return +// false. timeout==0 polls, timeout<0 waits forever. +bool mp_cancel_wait(struct mp_cancel *c, double timeout); + +// Restore original state. (Allows reusing a mp_cancel.) +void mp_cancel_reset(struct mp_cancel *c); + +// win32 "Event" HANDLE that indicates the current mp_cancel state. +void *mp_cancel_get_event(struct mp_cancel *c); + +// The FD becomes readable if mp_cancel_test() would return true. +// Don't actually read from it, just use it for poll(). +int mp_cancel_get_fd(struct mp_cancel *c); diff --git a/osdep/subprocess-posix.c b/osdep/subprocess-posix.c index a5fe43c6d4..ff78eb42f8 100644 --- a/osdep/subprocess-posix.c +++ b/osdep/subprocess-posix.c @@ -26,8 +26,9 @@ #include "osdep/subprocess.h" -#include "osdep/io.h" #include "common/common.h" +#include "misc/thread_tools.h" +#include "osdep/io.h" #include "stream/stream.h" extern char **environ; diff --git a/osdep/subprocess-win.c b/osdep/subprocess-win.c index bbb1f6f7fd..b5a9e1a24d 100644 --- a/osdep/subprocess-win.c +++ b/osdep/subprocess-win.c @@ -27,6 +27,7 @@ #include "common/common.h" #include "stream/stream.h" #include "misc/bstr.h" +#include "misc/thread_tools.h" static void write_arg(bstr *cmdline, char *arg) { diff --git a/player/main.c b/player/main.c index c51f93a430..6d2b862e02 100644 --- a/player/main.c +++ b/player/main.c @@ -54,7 +54,7 @@ #include "audio/out/ao.h" #include "demux/demux.h" -#include "stream/stream.h" +#include "misc/thread_tools.h" #include "sub/osd.h" #include "video/out/vo.h" diff --git a/stream/cache.c b/stream/cache.c index fb7927f0b1..424f27910f 100644 --- a/stream/cache.c +++ b/stream/cache.c @@ -54,6 +54,7 @@ #include "common/msg.h" #include "common/tags.h" +#include "misc/thread_tools.h" #include "options/options.h" #include "stream.h" diff --git a/stream/stream.c b/stream/stream.c index 4f63236d6a..072672d1ed 100644 --- a/stream/stream.c +++ b/stream/stream.c @@ -17,16 +17,12 @@ #include <stdio.h> #include <stdlib.h> -#include <sys/types.h> -#include <unistd.h> #include <limits.h> -#include <errno.h> #include <strings.h> #include <assert.h> #include <libavutil/common.h> -#include "osdep/atomic.h" #include "osdep/io.h" #include "mpv_talloc.h" @@ -36,6 +32,7 @@ #include "common/common.h" #include "common/global.h" #include "misc/bstr.h" +#include "misc/thread_tools.h" #include "common/msg.h" #include "options/options.h" #include "options/path.h" @@ -45,12 +42,6 @@ #include "options/m_option.h" #include "options/m_config.h" -#ifdef __MINGW32__ -#include <windows.h> -#else -#include <poll.h> -#endif - // Includes additional padding in case sizes get rounded up by sector size. #define TOTAL_BUFFER_SIZE (STREAM_MAX_BUFFER_SIZE + STREAM_MAX_SECTOR_SIZE) @@ -842,131 +833,6 @@ struct bstr stream_read_file(const char *filename, void *talloc_ctx, return res; } -#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; -} - -// Request abort. -void mp_cancel_trigger(struct mp_cancel *c) -{ - atomic_store(&c->triggered, true); - (void)write(c->wakeup_pipe[1], &(char){0}, 1); -} - -// Restore original state. (Allows reusing a mp_cancel.) -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; - } -} - -// Return whether the caller should abort. -// For convenience, c==NULL is allowed. -bool mp_cancel_test(struct mp_cancel *c) -{ - return c ? atomic_load_explicit(&c->triggered, memory_order_relaxed) : false; -} - -// Wait until the even is signaled. If the timeout (in seconds) expires, return -// false. timeout==0 polls, timeout<0 waits forever. -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; -} - -// The FD becomes readable if mp_cancel_test() would return true. -// Don't actually read from it, just use it for poll(). -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 - char **stream_get_proto_list(void) { char **list = NULL; diff --git a/stream/stream.h b/stream/stream.h index 3ce74ecd15..863c0cfd3c 100644 --- a/stream/stream.h +++ b/stream/stream.h @@ -254,14 +254,6 @@ stream_t *open_memory_stream(void *data, int len); void mp_url_unescape_inplace(char *buf); char *mp_url_escape(void *talloc_ctx, const char *s, const char *ok); -struct mp_cancel *mp_cancel_new(void *talloc_ctx); -void mp_cancel_trigger(struct mp_cancel *c); -bool mp_cancel_test(struct mp_cancel *c); -bool mp_cancel_wait(struct mp_cancel *c, double timeout); -void mp_cancel_reset(struct mp_cancel *c); -void *mp_cancel_get_event(struct mp_cancel *c); // win32 HANDLE -int mp_cancel_get_fd(struct mp_cancel *c); - // stream_file.c char *mp_file_url_to_filename(void *talloc_ctx, bstr url); char *mp_file_get_path(void *talloc_ctx, bstr url); diff --git a/stream/stream_file.c b/stream/stream_file.c index 2d0e3457c0..73048baefb 100644 --- a/stream/stream_file.c +++ b/stream/stream_file.c @@ -34,6 +34,7 @@ #include "common/common.h" #include "common/msg.h" +#include "misc/thread_tools.h" #include "stream.h" #include "options/m_option.h" #include "options/path.h" diff --git a/stream/stream_lavf.c b/stream/stream_lavf.c index 09866ff74f..fea6f4b62d 100644 --- a/stream/stream_lavf.c +++ b/stream/stream_lavf.c @@ -24,6 +24,7 @@ #include "common/msg.h" #include "common/tags.h" #include "common/av_common.h" +#include "misc/thread_tools.h" #include "stream.h" #include "options/m_config.h" #include "options/m_option.h" diff --git a/stream/stream_libarchive.c b/stream/stream_libarchive.c index bb25c6ad84..d02cb7e630 100644 --- a/stream/stream_libarchive.c +++ b/stream/stream_libarchive.c @@ -20,6 +20,7 @@ #include "misc/bstr.h" #include "common/common.h" +#include "misc/thread_tools.h" #include "stream.h" #include "stream_libarchive.h" |