player: update cache state only if requested

Add a mechanism to the client API code, which allows the player core to
query whether a client API event is needed at all. Use it for the cache
update.

In this case, this is probably a pure microoptimization; but the
mechanism will be useful for other things too.
This commit is contained in:
wm4 2014-08-28 17:35:50 +02:00
parent f9f436a490
commit fb1266c98b
3 changed files with 44 additions and 2 deletions

View File

@ -59,6 +59,7 @@ struct mp_client_api {
// -- protected by lock
struct mpv_handle **clients;
int num_clients;
uint64_t event_masks; // combined events of all clients, or 0 if unknown
};
struct observe_property {
@ -150,6 +151,13 @@ int mp_clients_num(struct MPContext *mpctx)
return num_clients;
}
static void invalidate_global_event_mask(struct mpv_handle *ctx)
{
pthread_mutex_lock(&ctx->clients->lock);
ctx->clients->event_masks = 0;
pthread_mutex_unlock(&ctx->clients->lock);
}
static struct mpv_handle *find_client(struct mp_client_api *clients,
const char *name)
{
@ -199,12 +207,14 @@ struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name
pthread_mutex_init(&client->wakeup_lock, NULL);
pthread_cond_init(&client->wakeup, NULL);
mpv_request_event(client, MPV_EVENT_TICK, 0);
MP_TARRAY_APPEND(clients, clients->clients, clients->num_clients, client);
clients->event_masks = 0;
pthread_mutex_unlock(&clients->lock);
mpv_request_event(client, MPV_EVENT_TICK, 0);
return client;
}
@ -502,6 +512,29 @@ static void dup_event_data(struct mpv_event *ev)
}
}
// Return whether there's any client listening to this event.
// If false is returned, the core doesn't need to send it.
bool mp_client_event_is_registered(struct MPContext *mpctx, int event)
{
struct mp_client_api *clients = mpctx->clients;
pthread_mutex_lock(&clients->lock);
if (!clients->event_masks) { // lazy update
for (int n = 0; n < clients->num_clients; n++) {
struct mpv_handle *ctx = clients->clients[n];
pthread_mutex_lock(&ctx->lock);
clients->event_masks |= ctx->event_mask | ctx->property_event_masks;
pthread_mutex_unlock(&ctx->lock);
}
}
bool r = clients->event_masks & (1ULL << event);
pthread_mutex_unlock(&clients->lock);
return r;
}
void mp_client_broadcast_event(struct MPContext *mpctx, int event, void *data)
{
struct mp_client_api *clients = mpctx->clients;
@ -555,6 +588,7 @@ int mpv_request_event(mpv_handle *ctx, mpv_event_id event, int enable)
uint64_t bit = 1ULL << event;
ctx->event_mask = enable ? ctx->event_mask | bit : ctx->event_mask & ~bit;
pthread_mutex_unlock(&ctx->lock);
invalidate_global_event_mask(ctx);
return 0;
}
@ -1140,6 +1174,7 @@ int mpv_observe_property(mpv_handle *ctx, uint64_t userdata,
ctx->property_event_masks |= prop->event_mask;
ctx->lowest_changed = 0;
pthread_mutex_unlock(&ctx->lock);
invalidate_global_event_mask(ctx);
return 0;
}
@ -1168,6 +1203,7 @@ int mpv_unobserve_property(mpv_handle *ctx, uint64_t userdata)
}
ctx->lowest_changed = 0;
pthread_mutex_unlock(&ctx->lock);
invalidate_global_event_mask(ctx);
return count;
}

View File

@ -17,6 +17,7 @@ int mp_clients_num(struct MPContext *mpctx);
void mp_client_broadcast_event(struct MPContext *mpctx, int event, void *data);
int mp_client_send_event(struct MPContext *mpctx, const char *client_name,
int event, void *data);
bool mp_client_event_is_registered(struct MPContext *mpctx, int event);
void mp_client_property_change(struct MPContext *mpctx, const char *name);
struct mpv_handle *mp_new_client(struct mp_client_api *clients, const char *name);

View File

@ -49,6 +49,7 @@
#include "video/out/vo.h"
#include "core.h"
#include "client.h"
#include "command.h"
void pause_player(struct MPContext *mpctx)
@ -556,7 +557,11 @@ static void handle_pause_on_low_cache(struct MPContext *mpctx)
}
// Also update cache properties.
bool busy = idle == 0 || !s.idle;
bool busy = idle == 0;
if (!s.idle) {
busy |= idle != -1;
busy |= mp_client_event_is_registered(mpctx, MP_EVENT_CACHE_UPDATE);
}
if (busy || mpctx->next_cache_update > 0) {
double now = mp_time_sec();
if (mpctx->next_cache_update <= now) {