Re: gtkmm-list Digest, Vol 196, Issue 1



I didn't dig too deep into the sigc docs, but the gtkmm multithreading documentation seemed clear enough to me after the coffee kicked in :)

First it states clearly
> Use Glib::Dispatcher to invoke gtkmm functions from worker threads

Then it says
> only the thread in which a main loop runs should call Glib::SignalIdle::connect()

The problem here is that I don't want to connect to every idle signal, I want a function to run once on the next idle. As you said, you can't connect in the worker thread to add that connect_once(). The important part is that the function is run (connected) once, not setup as a signal that is continuously being called every time the idle signal fires.

You mentioned running the lambdas in signal_idle, but how do you get the lambdas there in the first place? The function that calls the lambdas in signal_idle needs prior knowledge of where the lambas live to actually run them. You need some kind of a thread safe queue to get them there, no? That's basically what the code I wrote addresses.

I think that it should be possible to simply call g_idle_add with a std::function and no need for any queueing because from docs it seems like (hard to tell honestly) it should be safe to use from worker threads. I haven't seen anything like that in gtkmm though. The rust bindings have glib::idle_add in that manner, so I'm guessing we can do the same here.

Best,
-Ben

On Fri, Sep 11, 2020 at 8:00 AM <gtkmm-list-request gnome org> wrote:
Send gtkmm-list mailing list submissions to
        gtkmm-list gnome org

To subscribe or unsubscribe via the World Wide Web, visit
        https://mail.gnome.org/mailman/listinfo/gtkmm-list
or, via email, send a message with subject or body 'help' to
        gtkmm-list-request gnome org

You can reach the person managing the list at
        gtkmm-list-owner gnome org

When replying, please edit your Subject line so it is more specific
than "Re: Contents of gtkmm-list digest..."


Today's Topics:

   1. Invoking GTK main thread from other threads (Benjamin Quinn)
   2. Re: Invoking GTK main thread from other threads (Daniel Boles)
   3. Re: Invoking GTK main thread from other threads (Daniel Boles)


----------------------------------------------------------------------

Message: 1
Date: Thu, 10 Sep 2020 12:40:54 -0400
From: Benjamin Quinn <benlquinn gmail com>
To: gtkmm-list gnome org
Subject: Invoking GTK main thread from other threads
Message-ID:
        <CAL7GaSmu3HxFCuFzeBwWOjw2X8Ei3vBrdvnm4eHZ=-khVg1atA mail gmail com>
Content-Type: text/plain; charset="utf-8"

Hey all,

I've been working on a project using gtkmm and I was looking at the
multithreading docs. It seems that the recommended way to send data to the
UI thread is to use a Gtk::Dispatcher to signal data has changed and a
mutex to synchronize that data.

Using other bindings, such as GTK#, you have callback methods available to
run a function on the main thread, which can be safely invoked from other
threads.

I created a simple implementation of this for gtkmm here
<https://github.com/Blquinn/idlequeue>. The architecture is described in
the readme.

Let me know what you all think, or if there's any huge issues with it, I'm
new to c++ development, so there's a good chance this is not safe at all.

Best,
-Ben
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.gnome.org/archives/gtkmm-list/attachments/20200910/aca828ba/attachment.html>

------------------------------

Message: 2
Date: Thu, 10 Sep 2020 18:29:58 +0100
From: Daniel Boles <dboles src gmail com>
To: gtkmm-list <gtkmm-list gnome org>
Subject: Re: Invoking GTK main thread from other threads
Message-ID:
        <CAKChMKMsoLoGHYqrPfrJ9yVkEuVh7aKhw--0hyzLS_SMzD=opQ mail gmail com>
Content-Type: text/plain; charset="utf-8"

from your readme:

> GTK# and other gtk bindings supply a method to callback to the main
thread, which gtkmm does not.

I'm pretty sure it does. Or rather, GLib does, and GTK uses the GLib main
loop, and glibmm/gtkmm wrap both of those.

You simply connect to Glib::signal_idle(), passing a callback, which will
be called once the GLib main loop is running and has nothing of a higher
priority to do.

https://developer.gnome.org/glibmm/stable/classGlib_1_1SignalIdle.html
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.gnome.org/archives/gtkmm-list/attachments/20200910/a566efde/attachment.html>

------------------------------

Message: 3
Date: Thu, 10 Sep 2020 18:35:45 +0100
From: Daniel Boles <dboles src gmail com>
To: gtkmm-list <gtkmm-list gnome org>
Subject: Re: Invoking GTK main thread from other threads
Message-ID:
        <CAKChMKNCDCOYb2qE8iE9WePOTwTKxJz5hgfLVkvL_hoekiOuBQ mail gmail com>
Content-Type: text/plain; charset="utf-8"

That said, it's equally possible I am wrong and SignalIdle technically is
not thread-safe. I can't really make sense of the wording in the docs...

for connect_once(), we have:

> Because sigc::trackable
<http://library.gnome.org/devel/libsigc++/unstable/structsigc_1_1trackable.html>
is not thread-safe, if the slot represents a non-static method of a class
deriving from sigc::trackable
<http://library.gnome.org/devel/libsigc++/unstable/structsigc_1_1trackable.html>,
and the slot is created by sigc::mem_fun()
<http://library.gnome.org/devel/libsigc++/unstable/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419>,
connect_once()
<https://developer.gnome.org/glibmm/stable/classGlib_1_1SignalIdle.html#a94217dc63e35f96b5cee4c48f2cdd020>
should only be called from the thread where the SignalIdle
<https://developer.gnome.org/glibmm/stable/classGlib_1_1SignalIdle.html>
object's MainContext
<https://developer.gnome.org/glibmm/stable/classGlib_1_1MainContext.html>
runs. You can use, say, boost::bind() or, in C++11, std::bind()
<http://gcc.gnu.org/onlinedocs/libstdc++/latest-doxygen/a01513.html#ga7b2eddb726568256e49824ad01a05099>
or a C++11 lambda _expression_ instead of sigc::mem_fun()
<http://library.gnome.org/devel/libsigc++/unstable/group__mem__fun.html#gadf6b6d22c503b439019f0a2e77352419>
.

That makes enough sense and still leaves plenty cases for which it'll
definitely be safe.

but for connect(), we have the unconditional:

> This method is not thread-safe. You should call it, or manipulate the
returned sigc::connection
<http://library.gnome.org/devel/libsigc++/unstable/structsigc_1_1connection.html>
object, only from the thread where the SignalIdle
<https://developer.gnome.org/glibmm/stable/classGlib_1_1SignalIdle.html>
object's MainContext
<https://developer.gnome.org/glibmm/stable/classGlib_1_1MainContext.html>
runs.

I would expect the same condition(s) to apply to connect() as to
connect_once() - since AFAIK, all the once version does is just disconnect
itself automatically - but I might just be missing some obvious reason why
this can't be the case. And now I feel like maybe I've had this discussion
in the past...!

Anyway, I mentioned it because I have had the usual crashy behaviour
symbolic of trying to access widgets in threads other than the main one, in
my own projects, and wrapping the code doing said accesses in a lambda run
in SignalIdle has always fixed it. Maybe I've just been lucky so far?

Thoughts/corrections to me from those more experienced at doing
multi-threading with gtkmm are welcome.
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://mail.gnome.org/archives/gtkmm-list/attachments/20200910/f86e8bcc/attachment.html>

------------------------------

Subject: Digest Footer

_______________________________________________
gtkmm-list mailing list
gtkmm-list gnome org
https://mail.gnome.org/mailman/listinfo/gtkmm-list


------------------------------

End of gtkmm-list Digest, Vol 196, Issue 1
******************************************


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