mirror of https://github.com/mpv-player/mpv
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.
This commit is contained in:
parent
9d8b00f1d6
commit
ef827af06c
|
@ -25,6 +25,7 @@ API changes
|
||||||
|
|
||||||
::
|
::
|
||||||
|
|
||||||
|
1.14 - add mpv_wait_async_requests()
|
||||||
1.13 - add MPV_EVENT_QUEUE_OVERFLOW
|
1.13 - add MPV_EVENT_QUEUE_OVERFLOW
|
||||||
1.12 - add class Handle to qthelper.hpp
|
1.12 - add class Handle to qthelper.hpp
|
||||||
- improve opengl_cb.h API uninitialization behavior, and fix the qml
|
- improve opengl_cb.h API uninitialization behavior, and fix the qml
|
||||||
|
|
|
@ -167,7 +167,7 @@ extern "C" {
|
||||||
* relational operators (<, >, <=, >=).
|
* relational operators (<, >, <=, >=).
|
||||||
*/
|
*/
|
||||||
#define MPV_MAKE_VERSION(major, minor) (((major) << 16) | (minor) | 0UL)
|
#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.
|
* 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);
|
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 {
|
typedef enum mpv_sub_api {
|
||||||
/**
|
/**
|
||||||
* For using mpv's OpenGL renderer on an external OpenGL context.
|
* For using mpv's OpenGL renderer on an external OpenGL context.
|
||||||
|
|
|
@ -38,5 +38,6 @@ mpv_set_wakeup_callback
|
||||||
mpv_suspend
|
mpv_suspend
|
||||||
mpv_terminate_destroy
|
mpv_terminate_destroy
|
||||||
mpv_unobserve_property
|
mpv_unobserve_property
|
||||||
|
mpv_wait_async_requests
|
||||||
mpv_wait_event
|
mpv_wait_event
|
||||||
mpv_wakeup
|
mpv_wakeup
|
|
@ -269,7 +269,7 @@ static void wakeup_client(struct mpv_handle *ctx)
|
||||||
pthread_mutex_lock(&ctx->wakeup_lock);
|
pthread_mutex_lock(&ctx->wakeup_lock);
|
||||||
if (!ctx->need_wakeup) {
|
if (!ctx->need_wakeup) {
|
||||||
ctx->need_wakeup = true;
|
ctx->need_wakeup = true;
|
||||||
pthread_cond_signal(&ctx->wakeup);
|
pthread_cond_broadcast(&ctx->wakeup);
|
||||||
if (ctx->wakeup_cb)
|
if (ctx->wakeup_cb)
|
||||||
ctx->wakeup_cb(ctx->wakeup_cb_ctx);
|
ctx->wakeup_cb(ctx->wakeup_cb_ctx);
|
||||||
if (ctx->wakeup_pipe[0] != -1)
|
if (ctx->wakeup_pipe[0] != -1)
|
||||||
|
@ -360,21 +360,25 @@ static void unlock_core(mpv_handle *ctx)
|
||||||
mp_dispatch_unlock(ctx->mpctx->dispatch);
|
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)
|
void mpv_detach_destroy(mpv_handle *ctx)
|
||||||
{
|
{
|
||||||
if (!ctx)
|
if (!ctx)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
mp_resume_all(ctx);
|
|
||||||
|
|
||||||
pthread_mutex_lock(&ctx->lock);
|
|
||||||
// reserved_events equals the number of asynchronous requests that weren't
|
// 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
|
// yet replied. In order to avoid that trying to reply to a removed client
|
||||||
// causes a crash, block until all asynchronous requests were served.
|
// causes a crash, block until all asynchronous requests were served.
|
||||||
ctx->event_mask = 0;
|
mpv_wait_async_requests(ctx);
|
||||||
while (ctx->reserved_events || ctx->properties_updating)
|
|
||||||
wait_wakeup(ctx, INT64_MAX);
|
|
||||||
pthread_mutex_unlock(&ctx->lock);
|
|
||||||
|
|
||||||
struct mp_client_api *clients = ctx->clients;
|
struct mp_client_api *clients = ctx->clients;
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue