summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorwm4 <wm4@nowhere>2015-02-02 17:24:33 +0100
committerwm4 <wm4@nowhere>2015-02-02 18:07:37 +0100
commitef827af06cbf334a497fb0de8c9b75188549d03e (patch)
tree7d745d909fbeeae7a8466fff32166a723aa72871
parent9d8b00f1d6624779ab0db946018042135ef28017 (diff)
downloadmpv-ef827af06cbf334a497fb0de8c9b75188549d03e.tar.bz2
mpv-ef827af06cbf334a497fb0de8c9b75188549d03e.tar.xz
client API: add mpv_wait_async_requests()
This does what it's documented to do. The implementation reuses the code in mpv_detach_destroy(). Due to the way async requests currently work, just sending a synchronous dummy request (like a "ignore" command) would be enough to ensure synchronization, but this code will continue to work even if this changes. The line "ctx->event_mask = 0;" is removed, but it shouldn't be needed. (If a client is somehow very slow to terminate, this could silence an annoying queue overflow message, but all in all it does nothing.) Calling mpv_wait_async_requests() and mpv_wait_event() concurrently is in theory allowed, so change pthread_cond_signal() to pthread_cond_broadcast() to avoid missed wakeups. As requested in issue #1542.
-rw-r--r--DOCS/client-api-changes.rst1
-rw-r--r--libmpv/client.h16
-rw-r--r--libmpv/mpv.def1
-rw-r--r--player/client.c20
4 files changed, 29 insertions, 9 deletions
diff --git a/DOCS/client-api-changes.rst b/DOCS/client-api-changes.rst
index 8fa325a870..626474779b 100644
--- a/DOCS/client-api-changes.rst
+++ b/DOCS/client-api-changes.rst
@@ -25,6 +25,7 @@ API changes
::
+ 1.14 - add mpv_wait_async_requests()
1.13 - add MPV_EVENT_QUEUE_OVERFLOW
1.12 - add class Handle to qthelper.hpp
- improve opengl_cb.h API uninitialization behavior, and fix the qml
diff --git a/libmpv/client.h b/libmpv/client.h
index 7208912ee0..500f03cd94 100644
--- a/libmpv/client.h
+++ b/libmpv/client.h
@@ -167,7 +167,7 @@ extern "C" {
* relational operators (<, >, <=, >=).
*/
#define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
-#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 13)
+#define MPV_CLIENT_API_VERSION MPV_MAKE_VERSION(1, 14)
/**
* Return the MPV_CLIENT_API_VERSION the mpv source has been compiled with.
@@ -1478,6 +1478,20 @@ void mpv_set_wakeup_callback(mpv_handle *ctx, void (*cb)(void *d), void *d);
*/
int mpv_get_wakeup_pipe(mpv_handle *ctx);
+/**
+ * Block until all asynchronous requests are done. This affects functions like
+ * mpv_command_async(), which return immediately and return their result as
+ * events.
+ *
+ * This is a helper, and somewhat equivalent to calling mpv_wait_event() in a
+ * loop until all known asynchronous requests have sent their reply as event,
+ * except that the event queue is not emptied.
+ *
+ * In case you called mpv_suspend() before, this will also forcibly reset the
+ * suspend counter of the given handle.
+ */
+void mpv_wait_async_requests(mpv_handle *ctx);
+
typedef enum mpv_sub_api {
/**
* For using mpv's OpenGL renderer on an external OpenGL context.
diff --git a/libmpv/mpv.def b/libmpv/mpv.def
index 5176beaa8a..d4d45874fa 100644
--- a/libmpv/mpv.def
+++ b/libmpv/mpv.def
@@ -38,5 +38,6 @@ mpv_set_wakeup_callback
mpv_suspend
mpv_terminate_destroy
mpv_unobserve_property
+mpv_wait_async_requests
mpv_wait_event
mpv_wakeup \ No newline at end of file
diff --git a/player/client.c b/player/client.c
index ae4f1f3898..1c24d5522e 100644
--- a/player/client.c
+++ b/player/client.c
@@ -269,7 +269,7 @@ static void wakeup_client(struct mpv_handle *ctx)
pthread_mutex_lock(&ctx->wakeup_lock);
if (!ctx->need_wakeup) {
ctx->need_wakeup = true;
- pthread_cond_signal(&ctx->wakeup);
+ pthread_cond_broadcast(&ctx->wakeup);
if (ctx->wakeup_cb)
ctx->wakeup_cb(ctx->wakeup_cb_ctx);
if (ctx->wakeup_pipe[0] != -1)
@@ -360,21 +360,25 @@ static void unlock_core(mpv_handle *ctx)
mp_dispatch_unlock(ctx->mpctx->dispatch);
}
+void mpv_wait_async_requests(mpv_handle *ctx)
+{
+ mp_resume_all(ctx);
+
+ pthread_mutex_lock(&ctx->lock);
+ while (ctx->reserved_events || ctx->properties_updating)
+ wait_wakeup(ctx, INT64_MAX);
+ pthread_mutex_unlock(&ctx->lock);
+}
+
void mpv_detach_destroy(mpv_handle *ctx)
{
if (!ctx)
return;
- mp_resume_all(ctx);
-
- pthread_mutex_lock(&ctx->lock);
// reserved_events equals the number of asynchronous requests that weren't
// yet replied. In order to avoid that trying to reply to a removed client
// causes a crash, block until all asynchronous requests were served.
- ctx->event_mask = 0;
- while (ctx->reserved_events || ctx->properties_updating)
- wait_wakeup(ctx, INT64_MAX);
- pthread_mutex_unlock(&ctx->lock);
+ mpv_wait_async_requests(ctx);
struct mp_client_api *clients = ctx->clients;