diff options
author | Kjell Ahlstedt <kjell.ahlstedt@bredband.net> | 2013-06-02 15:06:55 +0200 |
---|---|---|
committer | Kjell Ahlstedt <kjell.ahlstedt@bredband.net> | 2013-06-02 15:06:55 +0200 |
commit | 47f1dedf040506b4aa7d131311866d8121bdbd8b (patch) | |
tree | 455bb0a976a63e48ac5ca10120d119daaab32dd8 /glib/glibmm | |
parent | bd986b90252fc05c743e26afea27068a9f90c572 (diff) | |
download | glibmm-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.cc | 31 | ||||
-rw-r--r-- | glib/glibmm/main.h | 32 |
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(). */ |