Passing data between threads (non main thread to OS main thread) in GTK4

I am building a GTK application using GTK4. I am stuck with the problem on how to pass some data between threads in GTK. To be specific, I am presenting the problem in detail.

I have a Server and a Client module, where the Client displays the UI based on the data received from Server. The UI related operations happen on the OS Main thread where the GTK event loop runs. Whereas the communication with the Server happens on a non main thread. At some point, Server may send some update to the Client. The update will be received on the communication thread i.e. the non main thread. Since the intention is to update the UI (either modify the UI or Create a new window) based on the information received, somehow the information shall be passed to the OS main thread where event loop is running.

In GTK4 how to pass the information between threads (main to non-main or vice versa)?

I am deliberately avoiding g_idle_add / g_idle_timeout because it keeps running the function continuously or at regular intervals. I am looking for some GTK supported message passing mechanism without building my own message passing system.

The best option for applications is to use g_idle_add() and have your callback return G_SOURCE_REMOVE (i.e. FALSE) so that it only executes once. If it’s executing continuously, that’s because you’re returning G_SOURCE_CONTINUE (i.e. TRUE) or you’ve forgotten to return at all and the compiler decides to return the result of the last expression.

Hi! Actually g_idle_add is the preferred way to invoke a callback on the main thread. To make the callback run only one time you have to return G_SOURCE_REMOVE from it:

static gboolean
foo_cb ()
{
  /* ... */
  return G_SOURCE_REMOVE;
}

See GSourceFunc

For the other direction, use a GAsyncQueue

1 Like

(But warning for anybody reading this in the future: you can only do this in application code, where you know you want your callback to be invoked on the default main context. In libraries, you must always keep track of which GMainContext to use explicitly.)

1 Like

In my application, probably I cannot return G_SOURCE_REMOVE because I need the main thread to be informed every time the Client receives a communication from Server. And the application would not know how frequent or how many times that communication would happen. So it would need the g_idle_add callback to be active as long as the application runs.

That’s where my concern of continuous or frequent run of the callback function arise. I was looking for something like a push message mechanism where Client can initiate the message delivery to the main thread and notify it, instead of main thread running the callback function again and again.

OK, then I think what you want is GAsyncQueue. This is more difficult and dangerous, but sounds closer to what you’re looking for.

If you want to integrate it into the event loop, you could write a custom GSource that checks whether messages exist in the queue.