summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjellahlstedt@gmail.com>2020-03-15 15:38:15 +0100
committerKjell Ahlstedt <kjellahlstedt@gmail.com>2020-03-15 15:38:15 +0100
commit26a065dd5cee17650586c5d410180cdece8b18a1 (patch)
tree1ca206443ac21a90c34b3d0865e2ec8a6e67e08f
parent3261b2ad7e57f749d0fd63b7be7b937d4efeac91 (diff)
downloadglibmm-26a065dd5cee17650586c5d410180cdece8b18a1.tar.gz
Glib::MainContext: Add push/pop/get_thread_default()
See issue #56
-rw-r--r--glib/glibmm/main.cc20
-rw-r--r--glib/glibmm/main.h77
2 files changed, 93 insertions, 4 deletions
diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc
index 9eae11af..40d39c66 100644
--- a/glib/glibmm/main.cc
+++ b/glib/glibmm/main.cc
@@ -701,6 +701,26 @@ MainContext::remove_poll(PollFD& fd)
}
void
+MainContext::push_thread_default()
+{
+ g_main_context_push_thread_default(gobj());
+}
+
+void
+MainContext::pop_thread_default()
+{
+ g_main_context_pop_thread_default(gobj());
+}
+
+// static
+Glib::RefPtr<MainContext>
+MainContext::get_thread_default()
+{
+ // g_main_context_ref_thread_default() gives us a ref.
+ return Glib::wrap(g_main_context_ref_thread_default(), false);
+}
+
+void
MainContext::invoke(const sigc::slot<bool>& slot, int priority)
{
// Make a copy of slot on the heap.
diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h
index 547123ec..9a0ba45b 100644
--- a/glib/glibmm/main.h
+++ b/glib/glibmm/main.h
@@ -415,10 +415,13 @@ public:
* @return The new MainContext.
*/
static Glib::RefPtr<MainContext> create();
- /** Returns the default main context.
- * This is the main context used for main loop functions when a main loop is not explicitly
- * specified.
- * @return The new MainContext.
+
+ /** Returns the global default main context.
+ * This is the main context used for main loop functions when a main loop
+ * is not explicitly specified, and corresponds to the "main" main loop.
+ *
+ * @return The global default main context.
+ * @see get_thread_default()
*/
static Glib::RefPtr<MainContext> get_default();
@@ -555,6 +558,72 @@ public:
*/
void remove_poll(PollFD& fd);
+ /** Acquires the context and sets it as the thread-default context for the current thread.
+ *
+ * This will cause certain asynchronous operations (such as most gio-based I/O)
+ * which are started in this thread to run under this context and deliver their
+ * results to its main loop, rather than running under the global
+ * default context in the main thread. Note that calling this function
+ * changes the context returned by get_thread_default(),
+ * not the one returned by get_default(), so it does not affect
+ * the context used by functions like g_idle_add().
+ *
+ * Normally you would call this function shortly after creating a new
+ * thread, passing it a Glib::MainContext which will be run by a
+ * Glib::MainLoop in that thread, to set a new default context for all
+ * async operations in that thread. In this case you may not need to
+ * ever call pop_thread_default(), assuming you want the
+ * new Glib::MainContext to be the default for the whole lifecycle of the
+ * thread.
+ *
+ * If you don't have control over how the new thread was created (e.g.
+ * if the new thread isn't newly created, or if the thread life
+ * cycle is managed by a GThreadPool), it is always suggested to wrap
+ * the logic that needs to use the new Glib::MainContext inside a
+ * push_thread_default() / pop_thread_default()
+ * pair, otherwise threads that are re-used will end up never explicitly
+ * releasing the Glib::MainContext reference they hold.
+ *
+ * In some cases you may want to schedule a single operation in a
+ * non-default context, or temporarily use a non-default context in
+ * the main thread. In that case, you can wrap the call to the
+ * asynchronous operation inside a push_thread_default() / pop_thread_default()
+ * pair, but it is up to you to ensure that no other asynchronous operations
+ * accidentally get started while the non-default context is active.
+ *
+ * Beware that libraries that predate this function may not correctly
+ * handle being used from a thread with a thread-default context. Eg,
+ * see Gio::File::supports_thread_contexts().
+ *
+ * @newin{2,64}
+ */
+ void push_thread_default();
+
+ /** Pops the context off the thread-default context stack (verifying that
+ * it was on the top of the stack).
+ *
+ * @newin{2,64}
+ */
+ void pop_thread_default();
+
+ /** Gets the thread-default MainContext for this thread.
+ * Asynchronous operations that want to be able to be run in contexts
+ * other than the default one should call this method to get a MainContext
+ * to add their Glib::Sources to. (Note that even in single-threaded
+ * programs applications may sometimes want to temporarily push a
+ * non-default context, so it is not safe to assume that this will
+ * always return the global default context if you are running in
+ * the default thread.)
+ *
+ * This method wraps g_main_context_ref_thread_default(),
+ * and not g_main_context_get_thread_default().
+ *
+ * @return The thread-default MainContext.
+ *
+ * @newin{2,64}
+ */
+ static Glib::RefPtr<MainContext> get_thread_default();
+
/** Invokes a function in such a way that this MainContext is owned during
* the invocation of @a slot.
*