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.
This commit is contained in:
Georges Basile Stavracas Neto
2020-04-16 15:11:53 -03:00
parent 61815ddccf
commit 494bd187d8
+60 -2
View File
@@ -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));