multithreadinggtkglibgdkgio

What GTK+ sub-process/threading/program execution/etc should I use if I want to launch a program from a GTK+ app?


If I wanted to run, say stty, which controls the terminal settings ( like character by character, or line by line), what would be the best way to do this. I want to use GTK+ tools. Would it be better to create a new thread, then run the program from that...or...?


Solution

  • As far as I know, there are 7 functions in the GTK+ API that do the specs you listed. 2 of those are subsets of a couple of them. Here is the list.

    g_spawn_
    g_thread_ 
    g_task_
    g_subprocess_
    gdk_threads_
    

    The last one belongs to GDK (Gimp Drawing Kit (why does it have threading?)), and the rest to GIO and Glib. Here are the subsets of g_thread_ and g_subprocess_:

    g_thread_pool_
    g_subprocess_launcher_
    

    You failed to identify in the question above whether or not you wanted stty run independent of the app, or, so to put it, connected to the app.

    I am now going to run through all the functions mentioned above, and explain their use. As always, check the GTK+ documentation for API Reference information. A good program that shows the GTK+ docs is devhelp. You can install it by typing in the terminal: sudo apt install devhelp. (Linux)

    g_spawn_ is a Glib function used as a more convenient version of the UNIX fork and exec functions. It has limited communication with the process. In some cases this is what you want, namely running a program whose output does not really have to be scanned. For a more advanced version of this, check out g_subprocess_.

    g_thread_ belongs to Glib also. The difference between a (sub)process and a thread is that threads share the same address space, whereas a (sub)process does not (they have their own memory). It is good to use threads because it is very easy to communicate between them, but you have to be careful, otherwise Heisenbugs will show up. This function supports mutex-es (plural), preventing race conditions. An example of a program that would use threads would be a image editor. One thread handles the mouse movements, the other handles the applying of effects, the other writes autosave information every minute or so.

    g_thread_pool_ is exactly the same as g_thread_ except that is has built-in handling of many threads. A browser, such as Chromium or Opera, would use this function if written in GTK+. Each thread would handle one tab, and then there would by a master thread, which would manage (destroy and create, etc.) the sub-threads.

    g_task_ represents a task to do. It is generally asynchronous, but it can be synchronous. You call g_task_new() and given that it is asynchronous, the code that called the function containing g_task_new() will resume. You indicate that the task is done by calling the g_task_return_ family of functions. Then the callback function is invoked, and that is the end. This has essentially the same use as a separate thread, which when it is destroyed, a callback is invoked.

    g_subprocess_ is a more convenient, sophisticated version of g_spawn_. The major advantage it has over the Glib spawning is its capabilities for asynchronous I/O: you can read from the output of one subprocess, and process the output, then send to the input stream of another process, without blocking the main loop. This is possible with g_spawn_ and other APIs, but is more difficult.

    gdk_threads_ is essentially the same as the Glib version. The only difference is on the automatic locking of individual data structure instances. g_thread_ does not do this for performance reasons. But you can lock them manually with g_thread_ whereas with gdk_threads_ it is done automatically. But because g_thread_ has more documentation, it is better to use it.

    So, the answer to your question is to use g_spawn_. It is the simplest, and when you write a program you try to keep everything simple.