summaryrefslogtreecommitdiff
path: root/src-ng/nautilus-context-scheduler.c
diff options
context:
space:
mode:
Diffstat (limited to 'src-ng/nautilus-context-scheduler.c')
-rw-r--r--src-ng/nautilus-context-scheduler.c166
1 files changed, 166 insertions, 0 deletions
diff --git a/src-ng/nautilus-context-scheduler.c b/src-ng/nautilus-context-scheduler.c
new file mode 100644
index 000000000..5f7723a9b
--- /dev/null
+++ b/src-ng/nautilus-context-scheduler.c
@@ -0,0 +1,166 @@
+/* Copyright (C) 2017 Ernestas Kulik <ernestask@gnome.org>
+ *
+ * This file is part of Nautilus.
+ *
+ * Nautilus is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation, either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * Nautilus is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with Nautilus. If not, see <https://www.gnu.org/licenses/>.
+ */
+
+#include "nautilus-context-scheduler.h"
+
+#include "nautilus-scheduler-private.h"
+
+struct _NautilusContextScheduler
+{
+ NautilusScheduler parent_instance;
+
+ GMainContext *context;
+ guint source_id;
+
+ GQueue *queue;
+};
+
+G_DEFINE_TYPE (NautilusContextScheduler, nautilus_context_scheduler,
+ NAUTILUS_TYPE_SCHEDULER)
+
+typedef struct
+{
+ GSource parent_instance;
+
+ NautilusContextScheduler *scheduler;
+} NautilusSource;
+
+G_LOCK_DEFINE_STATIC (table_mutex);
+static GHashTable *scheduler_table = NULL;
+
+static void
+queue (NautilusScheduler *scheduler,
+ NautilusCallback func,
+ gpointer func_data)
+{
+ NautilusContextScheduler *context_scheduler;
+ NautilusThreadWork *work;
+
+ context_scheduler = NAUTILUS_CONTEXT_SCHEDULER (scheduler);
+ work = nautilus_thread_work_new (func, func_data);
+
+ g_queue_push_tail (context_scheduler->queue, work);
+}
+
+static void
+nautilus_context_scheduler_class_init (NautilusContextSchedulerClass *klass)
+{
+ NautilusSchedulerClass *scheduler_class;
+
+ scheduler_class = NAUTILUS_SCHEDULER_CLASS (klass);
+
+ scheduler_class->queue = queue;
+}
+
+static gboolean
+source_prepare (GSource *source,
+ gint *timeout)
+{
+ NautilusSource *nautilus_source;
+
+ nautilus_source = (NautilusSource *) source;
+
+ *timeout = -1;
+
+ return !g_queue_is_empty (nautilus_source->scheduler->queue);
+}
+
+static gboolean
+source_check (GSource *source)
+{
+ NautilusSource *nautilus_source;
+
+ nautilus_source = (NautilusSource *) source;
+
+ return !g_queue_is_empty (nautilus_source->scheduler->queue);
+}
+
+static gboolean
+source_dispatch (GSource *source,
+ GSourceFunc callback,
+ gpointer user_data)
+{
+ return callback (user_data);
+}
+
+static GSourceFuncs source_funcs =
+{
+ source_prepare,
+ source_check,
+ source_dispatch,
+ NULL
+};
+
+static gboolean
+source_callback (gpointer data)
+{
+ NautilusContextScheduler *scheduler;
+ NautilusThreadWork *work;
+
+ scheduler = data;
+
+ while ((work = g_queue_pop_head (scheduler->queue)) != NULL)
+ {
+ nautilus_thread_work_run (work);
+ }
+
+ return G_SOURCE_CONTINUE;
+}
+
+static void
+nautilus_context_scheduler_init (NautilusContextScheduler *self)
+{
+ g_autoptr (GSource) source = NULL;
+
+ source = g_source_new (&source_funcs, sizeof (NautilusSource));
+
+ g_source_set_priority (source, G_PRIORITY_DEFAULT_IDLE);
+ g_source_set_callback (source, source_callback, self, NULL);
+
+ self->source_id = g_source_attach (source, self->context);
+}
+
+NautilusScheduler *
+nautilus_context_scheduler_get_for_context (GMainContext *context)
+{
+ NautilusContextScheduler *scheduler;
+
+ g_return_val_if_fail (context != NULL, NULL);
+
+ G_LOCK (table_mutex);
+
+ if (scheduler_table == NULL)
+ {
+ scheduler_table = g_hash_table_new_full (g_direct_hash, g_direct_equal,
+ NULL, g_object_unref);
+ }
+
+ scheduler = g_hash_table_lookup (scheduler_table, context);
+ if (scheduler == NULL)
+ {
+ scheduler = g_object_new (NAUTILUS_TYPE_CONTEXT_SCHEDULER, NULL);
+
+ scheduler->context = context;
+
+ g_hash_table_insert (scheduler_table, context, scheduler);
+ }
+
+ G_UNLOCK (table_mutex);
+
+ return NAUTILUS_SCHEDULER (scheduler);
+}