I've programmed a GTK3 application in C. To speed up performance I want to put some calculations in separate threads. Currently I have not yet decided how to exactly implement it. But I think I will go with a GTask that I will trigger to run in a separate thread.
I want to to emit certain status updates about the calculation progress on my GUI.
They way I imagine this:
I've got a calculation GObject with a do_the_stuff_async() function that triggers the thread/GTask. Ideally, I want to connect to a 'progress-changed' signal which gives me the current status that I can display on my GUI. Also it would be great to trigger an event once the task has finished, which seems doable with a GTask
How do I safely emit a signal from a GTask/GThread to my GTK main loop?
Because I have not yet started implementing the asynchronous stuff: Is a GTask a suitable way for this or should I use something entirely different?
A GTask is suitable for this.
To emit the signal in a different thread:
Store the GMainContext of the main thread somewhere, and pass it into the GTask as task data.
When you want to emit a signal, create a GSource with g_idle_source_new(), add a callback for it, and attach it to the GMainContext of the main thread. That will make the callback be called in the main thread the next time the main thread’s context iterates.
The callback should call g_signal_emit() as appropriate.
Unless you want to make the GObject that you’re emitting the signal from thread safe, you should not pass it to the GTask worker thread. My general advice would be to avoid locking by only passing immutable objects to and from the worker thread.
Note that you could use g_idle_add() to create an idle GSource and add it to the global default GMainContext (the one GTK uses in the main thread). However, this makes the use of the GMainContext less explicit, and hence makes the code less maintainable. It’s not an approach which I would recommend in general.
Related
I have an application that spawns a worker thread by calling g_thread_new(). The worker thread has to send progress information or probably occuring errors to the main thread that is updating the GUI based on received data.
Currently I'm using:
gtk_main_context_invoke(NULL, (GSourceFunc)update_gui, data);
with first parameter (of type GMainContext*) equal to NULL to run update_gui() in main loop context so that the worker can proceed doing the actual work.
When browsing the documentation I found a function:
guint g_idle_add (GSourceFunc function, gpointer data);
Would this function be more suitable for my application or should I use a completely different function for event transmission from worker to main thread?
Those functions are equivalent. g_main_context_invoke() is a wrapper around g_idle_add() which avoids the need for message passing if called on a GMainContext which is owned by the current thread (which is not the case in your example, but is harmless).
Note that the function is g_main_context_invoke(), not gtk_main_context_invoke(). To the best of my knowledge, the latter does not exist. Similarly, it’s g_idle_add() not gtk_idle_add().
Both g_main_context_invoke() and g_idle_add() are provided by GLib, not GTK. GTK uses GLib, but is not needed for this particular functionality.
I'm trying to use NetworkManager's libnm binding from a multithreaded program. Is libnm thread safe? I could not found any information about it.
libnm is written using glib and gobject. Although they don't seem to explicitly mention it in their doc, in general anything that uses glib runs on the main event loop and expects that the API will only be called on the main event loop (ie: on the thread that the event loop runs on).
Glib itself, however, is thread safe in general, or provides ways to ensure thread safety. For example, to connect to signal of libnm, you can use g_signal_connect from any thread; however the signal handler which you provide will be invoked on the thread running the main loop. Also, you can use something like g_idle_add from any thread, in order to schedule a function to be called from the main event loop.
You can also use the GTask lib to help you with threading in glib. Thre is more info about the Glib main context here.
My goal is to create an event handling infrastructure that will allow for registration of callback functions and calls to such functions based on time. Further, I plan to make the callback handler multithreaded as there are no restrictions on the type of callbacks, so a sequential architecture could cause unwanted blocking.
From my research I found that if a thread experiences undefined behavior and is terminated (.i.e. with SIGSEGV) then the entire process exits - which is obviously undesirable.
The question, then, is what options are there for ensuring thread independence? I do not think forking is a viable option in this case since the callbacks are not fully fledged programs, but rather simple routines to do various time-based tasks.
Correct me if I'm wrong.. If you want time-based tasks, I highly recommend you to try semaphores to control thread.
Block thread function like :
while(1){
sem_wait(my_semaphore);
code_that_needs_to_be_done_in_thread;
}
when you need your work in thread to be done just signal it from code whenever you want and howmany times you want:
sem_post(my_semaphore);
...
other_code;
sem_post(my_semaphore);
...
I'm building a fairly simple C application using GTK, but have to perform some blocking IO which will trigger updates to the GUI. In order to do this, I start a new pthread right before gtk_main() as such:
/* global variables */
GMainContext *mainc;
/* local variables */
FILE *fifo;
pthread_t reader;
/* main() */
mainc = g_main_context_default();
pthread_create(&reader, NULL, watch_fifo, argv[argc-1]);
gtk_main();
When the pthread reads some data, it updates the GUI like so:
g_main_context_invoke(mainc, set_icon, param);
Where set_icon is
gboolean set_icon(gpointer data)
{
char *p = (char*)data;
gtk_status_icon_set_from_icon_name(icon, p);
return FALSE;
}
This all works most of the time, but every now and again I get this curious error message:
[xcb] Unknown sequence number while processing queue
[xcb] Most likely this is a multi-threaded client and XInitThreads has not been called
[xcb] Aborting, sorry about that.
mktrayicon: xcb_io.c:274: poll_for_event: Assertion `!xcb_xlib_threads_sequence_lost' failed.
I thought the whole point of using g_main_context_invoke was to avoid issues with threads? Doing a bit of Googling, I came across gdk_threads_init, gdk_threads_enter and friends, but they all seem to be deprecated? I know the GTK documentation says that all GUI updaes should be performed on the main thread, but this does not combine all that well with blocking IO, and I'd prefer not to have to construct some complex communication mechanism between the threads.
And so, my question is, how should I correctly deal with this?
EDIT: The full code can be seen here
EDIT2: As an update based on #ptomato's answer, I've moved to GThreads and using gdk_threads_add_idle() as seen in this commit, but the problem is still present.
Call XInitThreads(). This should be done before gtk_init, that will stop the messages!
Something like this:
#include <X11/Xlib.h>
...
XInitThreads();
...
gtk_init(&argc, &argv);
I don't remember seeing these messages before GLIB 2.32, when
g_thread_init()/gdk_threads_init() were used.
You might want to check out g_thread_pool_new and g_thread_pool_push.
From thread, use g_main_context_invoke to execute in main loop or
just wrap thread between gdk_threads_enter()/gdk_threads_leave()
I do not use a tray so I can not easily check this. I think you are
correct about gdk_threads_add_idle using locks to protect GTK/GDK API.
There is nothing obvious to me that would cause these messages to
appear. The function description for gtk_status_icon_new_from_icon_name
states that "If the current icon theme is changed, the icon will be
updated appropriately. Which to me, implies your code is not the only
code that will access the X display, which could potentially be the
problem.
There is also some related info regarding XInitThreads() at
What is the downside of XInitThreads()?
Note that while GDK uses locks for the display, GTK/GDK do not ever
call XInitThreads.
On a side note: What's protecting the global variable "onclick", which
is passed to execl after a fork(), The child will not inherit the parent's
memory locks, and GLib mainloop is incompatible with fork().
Maybe you could copy the string to local variable.
I'm not sure if bare pthreads are guaranteed to work with GTK. You should use the GThread wrappers.
I think what the problem may be is that g_main_context_invoke() is adding set_icon() as an idle function. (It seems that that is what goes on behind the scenes, but I'm not sure.) Idle functions added using GLib's API, despite being executed on the main thread, need to hold the GDK lock. If you use the gdk_threads_add_idle() API (which is not deprecated) to invoke set_icon(), then everything should work properly with threading.
(Although this is just a wild guess.)
As a work around, if you just want to avoid blocking the UI while waiting for some IO you could use the asynchronous IO from GIO. That would avoid you having to manage threads yourself.
Edit: Thinking about it you could just mark your file descriptors as non-blocking and add them as a source to the glib main loop and it will poll them for you in the main event loop without having to mess about with threads.
You could avoid using threads by using gio_add_watch() which will invoke your callback function when there is data available on the channel.
I'm implementing a simple windowing library as a Ruby C extension. Windows have a handle_events! method that enters their native event loop.
The problem is that I want one event loop per window and the method blocks. I'd like the method to return immediately and let the loop run in a separate thread. What would be the best way to achieve this?
I tried using rb_thread_call_without_gvl to call the event loop function, and then use rb_thread_call_with_gvl in order to call the window's callbacks, which are Procs. Full source code can be found here.
It still works, but not as I intended: the method still blocks. Is this even possible with Ruby's threading model?
I had the very same problem to solve. And as rb_thread_call_with_gvl() was marked as experimental in 1.9.2 and it was not an exported symbol, I toke a different approach:
I called the blocking handle_event! function from a separate thread. I used a second ruby thread, that blocked on a message queue. While blocking on the message queue, the gvl was released with rb_thread_blocking_region().
If now the thread calling handle_event! was unblocked due to an event, it pulled all required information for the Proc's upcall together in a queue element and pushed that element onto the queue. The ruby thread received the element, returned from rb_thread_blocking_region() and thus reacquired the gvl and call the Proc with the information from the received element.
Kind regards
Torsten
As far as I understand, using rb_thread_call_with_gvl() still needs to be done on the same thread. i.e.: it's about releasing and taking the global lock, not really about changing threads. For example, a long running gzip function can run without the lock so that other ruby threads can run in parallel.
If you want your Procs called back on another thread, shouldn't you need to create a ruby thread for those Procs? Then on that thread, call out using rb_thread_call_without_gvl() to not hold the GVL (allowing other ruby threads to run), then when you have an event on the secondary window thread, call rb_thread_call_with_gvl() to grab the lock and then you should be right to call the Proc on that same thread.
That's the way I understand it... (not having done the C extension stuff very long.)