summaryrefslogtreecommitdiff
path: root/glib/glibmm
diff options
context:
space:
mode:
authorKjell Ahlstedt <kjell.ahlstedt@bredband.net>2013-06-02 15:06:55 +0200
committerKjell Ahlstedt <kjell.ahlstedt@bredband.net>2013-06-02 15:06:55 +0200
commit47f1dedf040506b4aa7d131311866d8121bdbd8b (patch)
tree455bb0a976a63e48ac5ca10120d119daaab32dd8 /glib/glibmm
parentbd986b90252fc05c743e26afea27068a9f90c572 (diff)
downloadglibmm-47f1dedf040506b4aa7d131311866d8121bdbd8b.tar.gz
Glib::MainContext: Add invoke().
* glib/glibmm/main.[h|cc]: Add Glib::MainContext::invoke(). Bug #668184.
Diffstat (limited to 'glib/glibmm')
-rw-r--r--glib/glibmm/main.cc31
-rw-r--r--glib/glibmm/main.h32
2 files changed, 63 insertions, 0 deletions
diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc
index 173f8317..f6707b7c 100644
--- a/glib/glibmm/main.cc
+++ b/glib/glibmm/main.cc
@@ -319,6 +319,28 @@ static void glibmm_signal_connect_once(const sigc::slot<void>& slot, int priorit
g_source_unref(source); // GMainContext holds a reference
}
+gboolean glibmm_main_context_invoke_callback(void* data)
+{
+ sigc::slot_base *const slot = reinterpret_cast<sigc::slot_base*>(data);
+
+ try
+ {
+ // Recreate the specific slot from the generic slot node.
+ return (*static_cast<sigc::slot<bool>*>(slot))();
+ }
+ catch(...)
+ {
+ Glib::exception_handlers_invoke();
+ }
+ return 0;
+}
+
+void glibmm_main_context_invoke_destroy_notify_callback(void* data)
+{
+ sigc::slot_base *const slot = reinterpret_cast<sigc::slot_base*>(data);
+ delete slot;
+}
+
} // anonymous namespace
@@ -655,6 +677,15 @@ void MainContext::remove_poll(PollFD& fd)
g_main_context_remove_poll(gobj(), fd.gobj());
}
+void MainContext::invoke(const sigc::slot<bool>& slot, int priority)
+{
+ // Make a copy of slot on the heap.
+ sigc::slot_base* const slot_copy = new sigc::slot<bool>(slot);
+
+ g_main_context_invoke_full(gobj(), priority, glibmm_main_context_invoke_callback,
+ slot_copy, glibmm_main_context_invoke_destroy_notify_callback);
+}
+
SignalTimeout MainContext::signal_timeout()
{
return SignalTimeout(gobj());
diff --git a/glib/glibmm/main.h b/glib/glibmm/main.h
index bc0dd215..cd07857f 100644
--- a/glib/glibmm/main.h
+++ b/glib/glibmm/main.h
@@ -524,6 +524,38 @@ public:
*/
void remove_poll(PollFD& fd);
+ /** Invokes a function in such a way that this MainContext is owned during
+ * the invocation of @a slot.
+ *
+ * If the context is owned by the current thread, @a slot is called
+ * directly. Otherwise, if the context is the thread-default main context
+ * of the current thread and acquire() succeeds, then
+ * @a slot is called and release() is called afterwards.
+ *
+ * In any other case, an idle source is created to call @a slot and
+ * that source is attached to the context (presumably to be run in another
+ * thread).
+ *
+ * Note that, as with normal idle functions, @a slot should probably
+ * return <tt>false</tt>. If it returns <tt>true</tt>, it will be continuously
+ * run in a loop (and may prevent this call from returning).
+ *
+ * If an idle source is created to call @a slot, invoke() may return before
+ * @a slot is called.
+ *
+ * Because sigc::trackable is not thread-safe, if the slot represents a
+ * non-static method of a class deriving from sigc::trackable, and the slot is
+ * created by sigc::mem_fun(), invoke() should only be called from
+ * the thread where the context runs. You can use, say, boost::bind() or,
+ * in C++11, std::bind() or a C++11 lambda expression instead of sigc::mem_fun().
+ *
+ * @param slot A slot to call.
+ * @param priority The priority of the idle source, if one is created.
+ *
+ * @newin{2,38}
+ */
+ void invoke(const sigc::slot<bool>& slot, int priority = PRIORITY_DEFAULT);
+
/** Timeout signal, attached to this MainContext.
* @return A signal proxy; you want to use SignalTimeout::connect().
*/