[glibmm] Glib::MainContext: Add invoke().



commit 47f1dedf040506b4aa7d131311866d8121bdbd8b
Author: Kjell Ahlstedt <kjell ahlstedt bredband net>
Date:   Sun Jun 2 15:06:55 2013 +0200

    Glib::MainContext: Add invoke().
    
    * glib/glibmm/main.[h|cc]: Add Glib::MainContext::invoke(). Bug #668184.

 ChangeLog           |    6 ++++++
 glib/glibmm/main.cc |   31 +++++++++++++++++++++++++++++++
 glib/glibmm/main.h  |   32 ++++++++++++++++++++++++++++++++
 3 files changed, 69 insertions(+), 0 deletions(-)
---
diff --git a/ChangeLog b/ChangeLog
index 7af8493..e67293e 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,9 @@
+2013-06-02  Kjell Ahlstedt  <kjell ahlstedt bredband net>
+
+       Glib::MainContext: Add invoke().
+
+       * glib/glibmm/main.[h|cc]: Add Glib::MainContext::invoke(). Bug #668184.
+
 2013-05-21  Kjell Ahlstedt  <kjell ahlstedt bredband net>
 
        Add missing includes in glibmm.h and bytearray.hg.
diff --git a/glib/glibmm/main.cc b/glib/glibmm/main.cc
index 173f831..f6707b7 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 bc0dd21..cd07857 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().
    */


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]