event-dispatcher: use an eventfd to make the source ready
- the source shouldn't become ready if there is nothing to do, otherwise idle sources do not run (since they have lower priority) - when the source becomes ready, we need a fd to wake up GLib's event dispatching mechanism to continue processing, otherwise nothing happens
This commit is contained in:

committed by
Julian Bouzas

parent
9db63e8ca6
commit
01a56496e2
@@ -13,6 +13,9 @@
|
|||||||
#include "private/registry.h"
|
#include "private/registry.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
|
|
||||||
|
#include <spa/support/plugin.h>
|
||||||
|
#include <spa/support/system.h>
|
||||||
|
|
||||||
struct _WpEvent
|
struct _WpEvent
|
||||||
{
|
{
|
||||||
grefcount ref;
|
grefcount ref;
|
||||||
@@ -144,6 +147,8 @@ struct _WpEventDispatcher
|
|||||||
GSource *source; /* the event loop source */
|
GSource *source; /* the event loop source */
|
||||||
GList *events; /* the events stack */
|
GList *events; /* the events stack */
|
||||||
WpEvent *rescan_event;
|
WpEvent *rescan_event;
|
||||||
|
struct spa_system *system;
|
||||||
|
int eventfd;
|
||||||
};
|
};
|
||||||
|
|
||||||
G_DEFINE_TYPE (WpEventDispatcher, wp_event_dispatcher, G_TYPE_OBJECT)
|
G_DEFINE_TYPE (WpEventDispatcher, wp_event_dispatcher, G_TYPE_OBJECT)
|
||||||
@@ -162,13 +167,16 @@ static gboolean
|
|||||||
wp_event_source_check (GSource * s)
|
wp_event_source_check (GSource * s)
|
||||||
{
|
{
|
||||||
WpEventDispatcher *d = WP_EVENT_SOURCE_DISPATCHER (s);
|
WpEventDispatcher *d = WP_EVENT_SOURCE_DISPATCHER (s);
|
||||||
return d && d->events;
|
return d && d->events &&
|
||||||
|
!((WpEvent *) g_list_first (d->events)->data)->current_hook_in_async;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
on_event_hook_done (WpEventHook * hook, GAsyncResult * res, WpEvent * event)
|
on_event_hook_done (WpEventHook * hook, GAsyncResult * res, WpEvent * event)
|
||||||
{
|
{
|
||||||
g_autoptr (GError) error = NULL;
|
g_autoptr (GError) error = NULL;
|
||||||
|
g_autoptr (WpEventDispatcher) dispatcher =
|
||||||
|
wp_event_hook_get_dispatcher (hook);
|
||||||
|
|
||||||
g_assert (event->current_hook_in_async == hook);
|
g_assert (event->current_hook_in_async == hook);
|
||||||
|
|
||||||
@@ -177,12 +185,17 @@ on_event_hook_done (WpEventHook * hook, GAsyncResult * res, WpEvent * event)
|
|||||||
wp_message_object (hook, "failed: %s", error->message);
|
wp_message_object (hook, "failed: %s", error->message);
|
||||||
|
|
||||||
g_clear_object (&event->current_hook_in_async);
|
g_clear_object (&event->current_hook_in_async);
|
||||||
|
spa_system_eventfd_write (dispatcher->system, dispatcher->eventfd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
static gboolean
|
static gboolean
|
||||||
wp_event_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
|
wp_event_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
|
||||||
{
|
{
|
||||||
WpEventDispatcher *d = WP_EVENT_SOURCE_DISPATCHER (s);
|
WpEventDispatcher *d = WP_EVENT_SOURCE_DISPATCHER (s);
|
||||||
|
uint64_t count;
|
||||||
|
|
||||||
|
/* clear the eventfd */
|
||||||
|
spa_system_eventfd_read (d->system, d->eventfd, &count);
|
||||||
|
|
||||||
/* get the highest priority event */
|
/* get the highest priority event */
|
||||||
GList *levent = g_list_first (d->events);
|
GList *levent = g_list_first (d->events);
|
||||||
@@ -266,6 +279,8 @@ wp_event_dispatcher_finalize (GObject * object)
|
|||||||
g_source_destroy (self->source);
|
g_source_destroy (self->source);
|
||||||
g_clear_pointer (&self->source, g_source_unref);
|
g_clear_pointer (&self->source, g_source_unref);
|
||||||
|
|
||||||
|
close (self->eventfd);
|
||||||
|
|
||||||
g_clear_pointer (&self->hooks, g_ptr_array_unref);
|
g_clear_pointer (&self->hooks, g_ptr_array_unref);
|
||||||
g_weak_ref_clear (&self->core);
|
g_weak_ref_clear (&self->core);
|
||||||
|
|
||||||
@@ -300,6 +315,17 @@ wp_event_dispatcher_get_instance (WpCore * core)
|
|||||||
if (G_UNLIKELY (!dispatcher)) {
|
if (G_UNLIKELY (!dispatcher)) {
|
||||||
dispatcher = g_object_new (WP_TYPE_EVENT_DISPATCHER, NULL);
|
dispatcher = g_object_new (WP_TYPE_EVENT_DISPATCHER, NULL);
|
||||||
g_weak_ref_set (&dispatcher->core, core);
|
g_weak_ref_set (&dispatcher->core, core);
|
||||||
|
|
||||||
|
struct pw_context *context = wp_core_get_pw_context (core);
|
||||||
|
uint32_t n_support;
|
||||||
|
const struct spa_support *support =
|
||||||
|
pw_context_get_support (context, &n_support);
|
||||||
|
dispatcher->system =
|
||||||
|
spa_support_find (support, n_support, SPA_TYPE_INTERFACE_System);
|
||||||
|
|
||||||
|
dispatcher->eventfd = spa_system_eventfd_create (dispatcher->system, 0);
|
||||||
|
g_source_add_unix_fd (dispatcher->source, dispatcher->eventfd, G_IO_IN);
|
||||||
|
|
||||||
g_source_attach (dispatcher->source, wp_core_get_g_main_context (core));
|
g_source_attach (dispatcher->source, wp_core_get_g_main_context (core));
|
||||||
wp_registry_register_object (registry, g_object_ref (dispatcher));
|
wp_registry_register_object (registry, g_object_ref (dispatcher));
|
||||||
}
|
}
|
||||||
@@ -360,6 +386,9 @@ wp_event_dispatcher_push_event (WpEventDispatcher * self, WpEvent * event)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* wakeup the GSource */
|
||||||
|
spa_system_eventfd_write (self->system, self->eventfd, 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
Reference in New Issue
Block a user