summaryrefslogtreecommitdiff
path: root/gjs/mainloop.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'gjs/mainloop.cpp')
-rw-r--r--gjs/mainloop.cpp55
1 files changed, 55 insertions, 0 deletions
diff --git a/gjs/mainloop.cpp b/gjs/mainloop.cpp
new file mode 100644
index 00000000..efe9d05a
--- /dev/null
+++ b/gjs/mainloop.cpp
@@ -0,0 +1,55 @@
+/* -*- mode: C++; c-basic-offset: 4; indent-tabs-mode: nil; -*- */
+// SPDX-License-Identifier: MIT OR LGPL-2.0-or-later
+// SPDX-FileCopyrightText: 2021 Evan Welsh <contact@evanwelsh.com>
+
+#include <gio/gio.h>
+#include <glib.h>
+
+#include "gjs/context-private.h"
+#include "gjs/mainloop.h"
+
+namespace Gjs {
+
+MainLoop::MainLoop() { m_refcount = 0; }
+
+void MainLoop::ref() { m_refcount++; }
+
+bool MainLoop::unref() {
+ if (m_refcount == 0)
+ return false;
+
+ m_refcount--;
+ return true;
+}
+
+void MainLoop::spin(GjsContext* context) {
+ auto priv = GjsContextPrivate::from_object(context);
+
+ // Check if System.exit() has been called.
+ if (priv->should_exit(nullptr))
+ return;
+
+ GjsAutoPointer<GMainContext, GMainContext, g_main_context_unref>
+ main_context(g_main_context_ref_thread_default());
+
+ do {
+ if (priv->should_exit(nullptr))
+ break;
+
+ // Allow the loop to block if the event loop is referenced.
+ bool can_block = m_refcount > 0;
+ // Only run the loop if there are pending jobs.
+ if (g_main_context_pending(main_context))
+ g_main_context_iteration(main_context, can_block);
+
+ // Check if System.exit() has been called.
+ if (priv->should_exit(nullptr))
+ break;
+ } while (
+ // If there are pending sources or the job queue is not empty
+ (m_refcount > 0 || !priv->empty()) &&
+ // and System.exit() has not been called
+ // continue spinning the event loop.
+ !priv->should_exit(nullptr));
+}
+}; // namespace Gjs