From 494bd187d8ee43ba5790b6509ab4af0f16227605 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Thu, 16 Apr 2020 15:11:53 -0300 Subject: [PATCH] timeline: Cancel additions and removals When we add an event to the queue, and later remove it, if the event is still in the queue, we can just cancel both out and save the timeline some processing time. --- src/core/gcal-timeline.c | 62 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 60 insertions(+), 2 deletions(-) diff --git a/src/core/gcal-timeline.c b/src/core/gcal-timeline.c index 2369651e..bacc2fa6 100644 --- a/src/core/gcal-timeline.c +++ b/src/core/gcal-timeline.c @@ -77,6 +77,7 @@ struct _GcalTimeline GCancellable *cancellable; + GHashTable *queued_adds; GQueue *event_queue; GSource *timeline_source; @@ -101,6 +102,13 @@ static GParamSpec *properties [N_PROPS] = { NULL, }; * Auxiliary methods */ +static gchar* +format_subscriber_event_id (GcalTimelineSubscriber *subscriber, + GcalEvent *event) +{ + return g_strdup_printf ("%s:%s", G_OBJECT_TYPE_NAME (subscriber), gcal_event_get_uid (event)); +} + static void queue_data_free (QueueData *queue_data) { @@ -118,6 +126,7 @@ queue_event_data (GcalTimeline *self, GcalEvent *old_event, gboolean update_range_tree) { + g_autofree gchar *subscriber_event_id = NULL; QueueData *queue_data; queue_data = g_new0 (QueueData, 1); @@ -128,7 +137,49 @@ queue_event_data (GcalTimeline *self, queue_data->old_event = old_event ? g_object_ref (old_event) : NULL; queue_data->update_range_tree = update_range_tree; + subscriber_event_id = format_subscriber_event_id (subscriber, event); + + switch (queue_event) + { + case ADD_EVENT: + case UPDATE_EVENT: + break; + case REMOVE_EVENT: + { + GList *queued_add_link; + + queued_add_link = g_hash_table_lookup (self->queued_adds, subscriber_event_id); + if (queued_add_link) + { + QueueData *queued_add = queued_add_link->data; + + GCAL_TRACE_MSG ("Removing ADD_EVENT for event '%s' (%s) from event queue", + gcal_event_get_summary (event), + subscriber_event_id); + + g_hash_table_remove (self->queued_adds, subscriber_event_id); + g_queue_delete_link (self->event_queue, queued_add_link); + queue_data_free (queued_add); + return; + } + } + break; + } + g_queue_push_tail (self->event_queue, queue_data); + + switch (queue_event) + { + case ADD_EVENT: + g_hash_table_insert (self->queued_adds, + g_steal_pointer (&subscriber_event_id), + g_queue_peek_tail_link (self->event_queue)); + break; + + case UPDATE_EVENT: + case REMOVE_EVENT: + break; + } } static inline gboolean @@ -608,6 +659,7 @@ timeline_source_dispatch (GSource *source, while (processed_events < BATCH_SIZE && !g_queue_is_empty (self->event_queue)) { GcalTimelineSubscriber *subscriber; + g_autofree gchar *subscriber_event_id = NULL; GcalRange *event_range; QueueData *queue_data; GcalEvent *event; @@ -617,10 +669,12 @@ timeline_source_dispatch (GSource *source, event = queue_data->event; subscriber = queue_data->subscriber; event_range = gcal_event_get_range (event); + subscriber_event_id = format_subscriber_event_id (subscriber, event); /* The subscriber may have been removed already */ if (!g_hash_table_contains (self->subscribers, subscriber)) { + g_hash_table_remove (self->queued_adds, subscriber_event_id); queue_data_free (queue_data); continue; } @@ -628,10 +682,12 @@ timeline_source_dispatch (GSource *source, switch (queue_data->queue_event) { case ADD_EVENT: - GCAL_TRACE_MSG ("Processing ADD_EVENT for event '%s' (%s)", + GCAL_TRACE_MSG ("Processing ADD_EVENT for event '%s' (%s) (in queued_adds: %d)", gcal_event_get_summary (event), - gcal_event_get_uid (event)); + gcal_event_get_uid (event), + g_hash_table_contains (self->queued_adds, subscriber_event_id)); + g_hash_table_remove (self->queued_adds, subscriber_event_id); if (queue_data->update_range_tree) gcal_range_tree_add_range (self->events, event_range, g_object_ref (event)); @@ -708,6 +764,7 @@ gcal_timeline_finalize (GObject *object) g_clear_pointer (&self->events, gcal_range_tree_unref); g_clear_pointer (&self->calendars, g_hash_table_destroy); g_clear_pointer (&self->subscribers, g_hash_table_destroy); + g_clear_pointer (&self->queued_adds, g_hash_table_destroy); g_clear_pointer (&self->subscriber_ranges, gcal_range_tree_unref); g_source_destroy (self->timeline_source); @@ -829,6 +886,7 @@ gcal_timeline_init (GcalTimeline *self) self->subscribers = g_hash_table_new_full (NULL, NULL, g_object_unref, (GDestroyNotify) gcal_range_unref); self->subscriber_ranges = gcal_range_tree_new (); self->event_queue = g_queue_new (); + self->queued_adds = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL); /* Timeline source */ timeline_source = (TimelineSource*) g_source_new (&timeline_source_funcs, sizeof (TimelineSource));