event-dispatcher: after-events hooks to get the trigger event info

after-events hooks will get the original event triggering it, instead of the
rescan event.

after-events hook can register with any event, but it is called with rescan event
info. This is so because, after-events hook run after all the on-events hooks
are done with and as a part of the rescan event. so it is triggered with rescan
event data, which doesnt carry much info, instead of rescan event, it makes more
sense to call the after-events hook with the original event which triggered it.
This commit is contained in:
Ashok Sidipotu
2022-08-05 07:32:48 +05:30
committed by Julian Bouzas
parent 72226e3934
commit 3ff9f240c8
4 changed files with 143 additions and 23 deletions

View File

@@ -200,6 +200,7 @@ void
wp_event_stop_processing (WpEvent * self) wp_event_stop_processing (WpEvent * self)
{ {
g_return_if_fail (self != NULL); g_return_if_fail (self != NULL);
wp_debug ("stopping event(%s)", self->name);
g_cancellable_cancel (self->cancellable); g_cancellable_cancel (self->cancellable);
} }
@@ -250,6 +251,9 @@ on_event_hook_done (WpEventHook * hook, GAsyncResult * res, WpEvent * event)
error->domain != G_IO_ERROR && error->code != G_IO_ERROR_CANCELLED) error->domain != G_IO_ERROR && error->code != G_IO_ERROR_CANCELLED)
wp_message_object (hook, "failed: %s", error->message); wp_message_object (hook, "failed: %s", error->message);
if (dispatcher->rescan_event == event)
wp_event_hook_set_event (event->current_hook_in_async, NULL);
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); spa_system_eventfd_write (dispatcher->system, dispatcher->eventfd, 1);
} }
@@ -284,8 +288,10 @@ wp_event_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
return G_SOURCE_CONTINUE; return G_SOURCE_CONTINUE;
/* remove the remaining hooks if the event was cancelled */ /* remove the remaining hooks if the event was cancelled */
if (g_cancellable_is_cancelled (event->cancellable) && event->hooks) if (g_cancellable_is_cancelled (event->cancellable) && event->hooks) {
wp_debug_object (d, "event(%s) cancelled remove it", event->name);
g_list_free_full (g_steal_pointer (&event->hooks), g_object_unref); g_list_free_full (g_steal_pointer (&event->hooks), g_object_unref);
}
/* avoid duplicate entries in chain */ /* avoid duplicate entries in chain */
if (!d->events_chain || !strstr (d->events_chain, event->name)) { if (!d->events_chain || !strstr (d->events_chain, event->name)) {
@@ -300,6 +306,7 @@ wp_event_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
if (lhook) { if (lhook) {
gchar *name = NULL; gchar *name = NULL;
gint priority; gint priority;
event->current_hook_in_async = WP_EVENT_HOOK (lhook->data); event->current_hook_in_async = WP_EVENT_HOOK (lhook->data);
event->hooks = g_list_delete_link (event->hooks, g_steal_pointer (&lhook)); event->hooks = g_list_delete_link (event->hooks, g_steal_pointer (&lhook));
name = wp_event_hook_get_name (event->current_hook_in_async); name = wp_event_hook_get_name (event->current_hook_in_async);
@@ -309,6 +316,20 @@ wp_event_source_dispatch (GSource * s, GSourceFunc callback, gpointer user_data)
wp_debug_object (d, "running hook <%p>(%s) and hooks chain (%s)", wp_debug_object (d, "running hook <%p>(%s) and hooks chain (%s)",
event->current_hook_in_async, name, event->hooks_chain); event->current_hook_in_async, name, event->hooks_chain);
if (event == d->rescan_event) {
WpEvent *hook_event =
wp_event_hook_get_event (event->current_hook_in_async);
/* for after-events, check if the corresponding event is cancelled */
if (g_cancellable_is_cancelled (hook_event->cancellable))
wp_debug_object (d, "remove hook(%s) as its trigger event(%s)"
" is cancelled", name, hook_event->name);
else
wp_event_hook_run (event->current_hook_in_async, hook_event,
event->cancellable, (GAsyncReadyCallback) on_event_hook_done,
event);
}
else
/* execute the hook, possibly async */ /* execute the hook, possibly async */
wp_event_hook_run (event->current_hook_in_async, event, wp_event_hook_run (event->current_hook_in_async, event,
event->cancellable, (GAsyncReadyCallback) on_event_hook_done, event); event->cancellable, (GAsyncReadyCallback) on_event_hook_done, event);
@@ -481,6 +502,8 @@ wp_event_dispatcher_push_event (WpEventDispatcher * self, WpEvent * event)
(GCompareFunc) hook_cmp_func); (GCompareFunc) hook_cmp_func);
wp_debug_object (self, "added rescan hook <%p>(%s(%d))", hook, wp_debug_object (self, "added rescan hook <%p>(%s(%d))", hook,
wp_event_hook_get_name (hook), wp_event_hook_get_priority (hook)); wp_event_hook_get_name (hook), wp_event_hook_get_priority (hook));
wp_event_hook_set_event (hook, event);
rescan_hooks_added = true; rescan_hooks_added = true;
} }
} }

View File

@@ -21,6 +21,8 @@ struct _WpEventHookPrivate
WpEventHookExecType exec_type; WpEventHookExecType exec_type;
GWeakRef dispatcher; GWeakRef dispatcher;
gchar *name; gchar *name;
/* event triggering the hook, useful for after-events. */
WpEvent *event_trigger;
}; };
enum { enum {
@@ -47,6 +49,7 @@ wp_event_hook_finalize (GObject * object)
WpEventHookPrivate *priv = wp_event_hook_get_instance_private (self); WpEventHookPrivate *priv = wp_event_hook_get_instance_private (self);
g_weak_ref_clear (&priv->dispatcher); g_weak_ref_clear (&priv->dispatcher);
g_clear_pointer (&priv->event_trigger, wp_event_unref);
g_free (priv->name); g_free (priv->name);
G_OBJECT_CLASS (wp_event_hook_parent_class)->finalize (object); G_OBJECT_CLASS (wp_event_hook_parent_class)->finalize (object);
@@ -130,6 +133,38 @@ wp_event_hook_class_init (WpEventHookClass * klass)
G_PARAM_READABLE | G_PARAM_STATIC_STRINGS)); G_PARAM_READABLE | G_PARAM_STATIC_STRINGS));
} }
/*!
* \brief Returns the event triggering the hook, this data is useful for
* after-events.
*
* \ingroup wpeventhook
* \param self the event hook
* \returns (transfer none) (nullable): the event
*/
WpEvent *
wp_event_hook_get_event (WpEventHook *self)
{
g_return_val_if_fail (WP_IS_EVENT_HOOK (self), 0);
WpEventHookPrivate *priv = wp_event_hook_get_instance_private (self);
return priv->event_trigger;
}
/*!
* \brief Sets the event triggering the hook
*
* \ingroup wpeventhook
* \param self the event hook
* \param event (transfer none) (nullable):the event associated with the hook
*/
void
wp_event_hook_set_event (WpEventHook *self, WpEvent *event)
{
WpEventHookPrivate *priv = wp_event_hook_get_instance_private (self);
g_clear_pointer (&priv->event_trigger, wp_event_unref);
if (event)
priv->event_trigger = wp_event_ref (event);
}
/*! /*!
* \brief Returns the priority of the hook * \brief Returns the priority of the hook
* *
@@ -191,6 +226,14 @@ wp_event_hook_get_dispatcher (WpEventHook * self)
return g_weak_ref_get (&priv->dispatcher); return g_weak_ref_get (&priv->dispatcher);
} }
/*!
* \brief Sets the dispatcher to the hook
*
* \ingroup wpeventhook
* \param self the event hook
* \param dispatcher (transfer none) (nullable) dispatcher to which the hook is
* to be registered.
*/
void void
wp_event_hook_set_dispatcher (WpEventHook * self, WpEventDispatcher * dispatcher) wp_event_hook_set_dispatcher (WpEventHook * self, WpEventDispatcher * dispatcher)
{ {

View File

@@ -29,8 +29,15 @@ typedef enum
{ {
WP_EVENT_HOOK_DEFAULT_PRIORITY_BASE = 0, WP_EVENT_HOOK_DEFAULT_PRIORITY_BASE = 0,
WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_POLICY = WP_EVENT_HOOK_DEFAULT_PRIORITY_BASE, WP_EVENT_HOOK_DEFAULT_PRIORITY_FIND_DEFINED_TARGET = WP_EVENT_HOOK_DEFAULT_PRIORITY_BASE,
WP_EVENT_HOOK_DEFAULT_PRIORITY_AFTER_EVENTS_DEFAULT_NODES_STATE_SAVE = WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_POLICY + PRIORITY_STEP, WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_DEFAULT_NODES = WP_EVENT_HOOK_DEFAULT_PRIORITY_AFTER_EVENTS_DEFAULT_NODES_STATE_SAVE + PRIORITY_STEP, WP_EVENT_HOOK_DEFAULT_PRIORITY_FIND_UNDEFINED_TARGET = WP_EVENT_HOOK_DEFAULT_PRIORITY_FIND_DEFINED_TARGET + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_FIND_BEST_TARGET = WP_EVENT_HOOK_DEFAULT_PRIORITY_FIND_UNDEFINED_TARGET + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_PREPARE_LINK = WP_EVENT_HOOK_DEFAULT_PRIORITY_FIND_BEST_TARGET + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_CREATE_LINK = WP_EVENT_HOOK_DEFAULT_PRIORITY_PREPARE_LINK + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_POLICY = WP_EVENT_HOOK_DEFAULT_PRIORITY_CREATE_LINK + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_AFTER_EVENTS_DEFAULT_NODES_STATE_SAVE = WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_POLICY + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_DEFAULT_NODES = WP_EVENT_HOOK_DEFAULT_PRIORITY_AFTER_EVENTS_DEFAULT_NODES_STATE_SAVE + PRIORITY_STEP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_NODE_ADDED = WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_POLICY + PRIORITY_JUMP, WP_EVENT_HOOK_DEFAULT_PRIORITY_NODE_ADDED = WP_EVENT_HOOK_DEFAULT_PRIORITY_RESCAN_POLICY + PRIORITY_JUMP,
WP_EVENT_HOOK_DEFAULT_PRIORITY_NODE_ADDED_RESTORE_STREAM = WP_EVENT_HOOK_DEFAULT_PRIORITY_NODE_ADDED, WP_EVENT_HOOK_DEFAULT_PRIORITY_NODE_ADDED_RESTORE_STREAM = WP_EVENT_HOOK_DEFAULT_PRIORITY_NODE_ADDED,
@@ -120,6 +127,12 @@ WP_PRIVATE_API
void wp_event_hook_set_dispatcher (WpEventHook * self, void wp_event_hook_set_dispatcher (WpEventHook * self,
WpEventDispatcher * dispatcher); WpEventDispatcher * dispatcher);
WP_API
void wp_event_hook_set_event (WpEventHook *self, WpEvent *event);
WP_API
WpEvent *wp_event_hook_get_event (WpEventHook *self);
WP_API WP_API
gboolean wp_event_hook_runs_for_event (WpEventHook * self, WpEvent * event); gboolean wp_event_hook_runs_for_event (WpEventHook * self, WpEvent * event);

View File

@@ -12,6 +12,7 @@ typedef struct {
WpBaseTestFixture base; WpBaseTestFixture base;
WpObjectManager *om; WpObjectManager *om;
GPtrArray *hooks_executed; GPtrArray *hooks_executed;
GPtrArray *events;
WpTransition *transition; WpTransition *transition;
} TestFixture; } TestFixture;
@@ -20,6 +21,7 @@ test_events_setup (TestFixture *self, gconstpointer user_data)
{ {
wp_base_test_fixture_setup (&self->base, 0); wp_base_test_fixture_setup (&self->base, 0);
self->hooks_executed = g_ptr_array_new (); self->hooks_executed = g_ptr_array_new ();
self->events = g_ptr_array_new ();
} }
static void static void
@@ -35,6 +37,7 @@ test_events_teardown (TestFixture *self, gconstpointer user_data)
{ \ { \
g_debug ("in hook_" #x); \ g_debug ("in hook_" #x); \
g_ptr_array_add (self->hooks_executed, hook_##x); \ g_ptr_array_add (self->hooks_executed, hook_##x); \
g_ptr_array_add (self->events, event); \
} }
HOOK_FUNC(a) HOOK_FUNC(a)
@@ -47,6 +50,7 @@ hook_quit (WpEvent * event, TestFixture * self)
{ {
g_debug ("in hook_quit"); g_debug ("in hook_quit");
g_ptr_array_add (self->hooks_executed, hook_quit); g_ptr_array_add (self->hooks_executed, hook_quit);
g_ptr_array_add (self->events, event);
g_main_loop_quit (self->base.loop); g_main_loop_quit (self->base.loop);
} }
@@ -55,6 +59,7 @@ test_events_basic (TestFixture * self, gconstpointer user_data)
{ {
g_autoptr (WpEventDispatcher) dispatcher = NULL; g_autoptr (WpEventDispatcher) dispatcher = NULL;
g_autoptr (WpEventHook) hook = NULL; g_autoptr (WpEventHook) hook = NULL;
WpEvent *event1 = NULL, *event2 = NULL;
dispatcher = wp_event_dispatcher_get_instance (self->base.core); dispatcher = wp_event_dispatcher_get_instance (self->base.core);
g_assert_nonnull (dispatcher); g_assert_nonnull (dispatcher);
@@ -101,37 +106,73 @@ test_events_basic (TestFixture * self, gconstpointer user_data)
wp_event_dispatcher_register_hook (dispatcher, hook); wp_event_dispatcher_register_hook (dispatcher, hook);
g_clear_object (&hook); g_clear_object (&hook);
/* first event */ /* first event run */
wp_event_dispatcher_push_event (dispatcher, event1 = wp_event_new ("type1", 10, NULL, NULL, NULL);
wp_event_new ("type1", 10, NULL, NULL, NULL)); wp_event_dispatcher_push_event (dispatcher, event1);
g_assert_cmpint (self->hooks_executed->len, ==, 0); g_assert_cmpint (self->hooks_executed->len, ==, 0);
g_main_loop_run (self->base.loop); g_main_loop_run (self->base.loop);
g_assert_cmpint (self->hooks_executed->len, ==, 4); g_assert_cmpint (self->hooks_executed->len, ==, 4);
g_assert (hook_c == self->hooks_executed->pdata[0]); g_assert (hook_c == self->hooks_executed->pdata[0]);
g_assert (event1 == self->events->pdata[0]);
g_assert (hook_a == self->hooks_executed->pdata[1]); g_assert (hook_a == self->hooks_executed->pdata[1]);
g_assert (hook_b == self->hooks_executed->pdata[2]); g_assert (event1 == self->events->pdata [1]);
g_assert (hook_quit == self->hooks_executed->pdata[3]); g_assert (hook_b == self->hooks_executed->pdata [2]);
g_assert (event1 == self->events->pdata [2]);
g_assert (hook_quit == self->hooks_executed->pdata [3]);
g_assert (event1 == self->events->pdata [3]);
g_ptr_array_remove_range (self->hooks_executed, 0, self->hooks_executed->len); g_ptr_array_remove_range (self->hooks_executed, 0, self->hooks_executed->len);
g_assert_cmpint (self->hooks_executed->len, ==, 0); g_assert_cmpint (self->hooks_executed->len, ==, 0);
g_ptr_array_remove_range (self->events, 0, self->events->len);
g_assert_cmpint (self->events->len, == , 0);
/* second event */ /* second event run */
wp_event_dispatcher_push_event (dispatcher, event1 = wp_event_new ("type1", 10,
wp_event_new ("type1", 10, wp_properties_new ("test.prop", "some-val", NULL), NULL, NULL);
wp_properties_new ("test.prop", "some-val", NULL), NULL, NULL)); event2 = wp_event_new ("type2", 100,
wp_event_dispatcher_push_event (dispatcher, wp_properties_new ("test.prop", "some-val", NULL), NULL, NULL);
wp_event_new ("type2", 100,
wp_properties_new ("test.prop", "some-val", NULL), NULL, NULL)); wp_event_dispatcher_push_event (dispatcher, event1);
wp_event_dispatcher_push_event (dispatcher, event2);
g_assert_cmpint (self->hooks_executed->len, ==, 0); g_assert_cmpint (self->hooks_executed->len, ==, 0);
g_main_loop_run (self->base.loop); g_main_loop_run (self->base.loop);
g_assert_cmpint (self->hooks_executed->len, ==, 5); g_assert_cmpint (self->hooks_executed->len, ==, 5);
g_assert (hook_d == self->hooks_executed->pdata[0]); g_assert (hook_d == self->hooks_executed->pdata [0]);
g_assert (hook_c == self->hooks_executed->pdata[1]); g_assert (event2 == self->events->pdata [0]);
g_assert (hook_a == self->hooks_executed->pdata[2]); g_assert (hook_c == self->hooks_executed->pdata [1]);
g_assert (hook_b == self->hooks_executed->pdata[3]); g_assert (event1 == self->events->pdata [1]);
g_assert (hook_quit == self->hooks_executed->pdata[4]); g_assert (hook_a == self->hooks_executed->pdata [2]);
g_assert (event1 == self->events->pdata [2]);
g_assert (hook_b == self->hooks_executed->pdata [3]);
g_assert (event1 == self->events->pdata [3]);
g_assert (hook_quit == self->hooks_executed->pdata [4]);
g_assert (event1 == self->events->pdata [4]);
g_ptr_array_remove_range (self->hooks_executed, 0, self->hooks_executed->len);
g_assert_cmpint (self->hooks_executed->len, == , 0);
g_ptr_array_remove_range (self->events, 0, self->events->len);
g_assert_cmpint (self->events->len, == , 0);
/* thrid event run to test event cancellation */
event1 = wp_event_new ("type1", 10,
wp_properties_new ("test.prop", "some-val", NULL), NULL, NULL);
event2 = wp_event_new ("type2", 100,
wp_properties_new ("test.prop", "some-val", NULL), NULL, NULL);
wp_event_dispatcher_push_event (dispatcher, event2);
wp_event_dispatcher_push_event (dispatcher, event1);
wp_event_stop_processing (event1);
g_assert_cmpint (self->hooks_executed->len, == , 0);
g_main_loop_run (self->base.loop);
g_assert_cmpint (self->hooks_executed->len, == , 2);
g_assert (hook_d == self->hooks_executed->pdata [0]);
g_assert (event2 == self->events->pdata [0]);
g_assert (hook_quit == self->hooks_executed->pdata [1]);
g_assert (event2 == self->events->pdata [1]);
} }
enum { enum {