Refactoring single threaded GUI code for multithreaded scenarious - c++

The usual scenario, there is an MFC/Win32/WTL/wxWidgets/Qt application that does something useful. It was designed to be single threaded, and there is some logic that handles errors/questions within processing blocks.
So, somewhere deep inside some class, a dialog can be fired that asks the user "Are you sure you want to complete the action?"/"Error with document layout" or something like that.
The problem is the dialog is fired from computationally heavy/strightforward code. Like FFT/image sharpening/file system de-fragmentation function, or something along the lines. Which could be launched in a worker thread easily, if not for the GUI. And would suit there better, as it would avoid GUI stalls that are so annoying for the user.
However, GUI cannot work in a worker thread, and dependency injection is pretty much impossible to do, because it would go down several layers of computational code. In a very unclean way from class interface standpoint, like someclass instance(data_in, data_out, param1, param2, GUI_class_ref) : m_GUI(GUI_class_ref), ... 3 or more levels deep.
Is there a pattern/checklist for such scenarios that can be used to marshall GUI prompts back to main thread and return the result back into the core of the computational code, if the code is split in multiple threads?

You can create synchronization context. It is a queue of commands to be executed by main thread. Worker thread adds command into this queue (which must be locked for single-thread access) and waits. Main thread processes this queue periodically, executes commands (for example, "Cancel operation" dialogs) and notifies worker threads about results.
In C#, this was done with delegates and arguments to call them. In C++, you can go with enum-coded messages to be processed in a switch (like messages in Windows programs.) Or create something with pointers to member functions + object pointer to call them from + arguments to call with.

You are at one classical old code refactoring crossroad. Proper isolation and dependency injection is infeasible, so you are left with making the GUI context globally accessible. That is creating a Singleton. It doesn't necessarily need to be the GUI context directly, so at least some isolation is achieved. It can be some kind of manager which has the GUI context and accepts just specific one purpose calls from the computation code. You could make the GUI thread class a friend of this manager and make the GUI callbacks (upon closing the dialog) private.
I could give more specific ideas what to write as i went through exactly the same challenge (threadization of existing heavy app). But i am confused whether you want only the GUI thread to be running freely, or the background computation as well. The example dialog prompt you gave is confusing as it suggests a decision which needs to be answered to know whether continue at all (which would mean that computation is on hold).

Related

The correct variant of implementation of the server-client in one application? Qt6

I am creating simple online chat with server and client in one application. I wrote client-side, but i don't know how will be correct use QTcpServer.
Need i create QTcpServer in new thread? So that I can connect to it as a client from this application. If yes, how do it? Or it's useless and not needed idea?
Need i create new thread for every new connection in order to process it?
I am developing a chat as a course project for a university
Assuming you are using Qt's networking APIs, you don't need to use multiple threads. The reason is that Qt's APIs are designed around a non-blocking event-loop model, so it is expected that no function-call should ever take more than a negligible amount of time (e.g. a few milliseconds) to return, after which the main thread's QEventLoop resumes execution and can therefore handle other tasks in a timely manner, all from within a single thread.
That said, there are a few optional methods in the Qt API that are blocking, and in a single-threaded application, calling those methods risks making your application un-responsive for (however long it takes for those methods to return). Fortunately those methods aren't necessary, and they are clearly documented. I recommend avoiding them, as there are always better, non-blocking ways to achieve the same result in Qt, e.g. by connecting the appropriate signals to the appropriate slots.
To sum up: threads aren't necessary in Qt-based networking, and your program will be simpler, more reliable, and easier to debug if you don't use threads. When implementing server-like functionality, a QTcpServer object is useful; you might want to have a look at this example program for cues on how to use it.

Signals instead of exceptions

Let's suppose we are developing a store, and, depending on the session state, the user is allowed to do different things. For example, suppose a widget must be blocked during a while in some specific moment, because some specific user actions, and the user tries again.
Of course, the most obvious implementation will be launching an exception in the corresponding function (the specific event handler), to say the action is currently blocked. That's similar to a concrete problem of mine. In that case, it was more convenient for me, instead of throwing an exception, make the function a "no-op", but emiting a boost::signal2's signal. The GUI does whatever he wants to do, inform the user or whatever. But perhaps the GUI only wants to inform the user once, so, it just disconnect to the signal after the first call.
And I liked it. It's pretty beautiful and elegant: to make it a no-op and emit a signal. No stack unwinding, functions can be marked as noexcept, you enable more optimizations in consequence, and you deal with the excepcional cases only when you want, connecting and desconnecting to the signals as wished.
Now it comes the question, what if I want to generalize the method substituting each exception for signals? even for non-GUI applications?
In that case, are boost::signals2 more inneficient than exceptions? Because it's a common hearing that try/catch blocks, no-noexcept functions, and stack unwinding causes overhead and avoid the compiler do a lot of possible optimizations. On the other hand, boost::signals2 is thread-safe, which causes extra overhead.
Is it my idea a bad idea at all?
I hope my question is not close for being "too broad" or "opinion-based", because its a question of design (and optimization) after all; although not too much specific, I have to admit.
Note: The GUI is a website. The thing is, I'm using Wt, a library to do websites in C++, which translate a hierarchy of widgets and signals to HTML/Javascript/Ajax, and my long-term project is to create a suite for creating GUIs in both, desktop/mobile (Qt) and web (Javascript) from a common infrastructure with an unique C++ back-end. Wt allows a mapping between C++/Javascript slots for a same event; for example, a click: if Javascript or Ajax is not available, the event is sent to the server and the C++ slot is called. If it is available, the event is executed on the client using the Javascript version. In case a same (GUI) event has more than one slot, the order of execution of slots is unspecified, and if both slots are C++ calls, they could be even executed in parallel on the server if there's enough threads available in the thread pool.

Should GTK+ interface run in a separate thread?

I'm taking my first steps in GTK+ (C++ and gtkmm more specificaly) and I have a rather conceptual doubts about how to best structure my program. Right now I just want my GUI to show what is happening in my C++ program by printing several values, and since my main thread is halted while the GUI window is running, I've come across solutions that separated both the processing/computing operations and the graphical interface in separate threads. Is this commonly accepted as the best way to do it, not at all, or not even relevant?
Unless you have a good reason, you are generally better off not creating new threads. Synchronization is hard to get right.
GUI programming is event driven (click on a button and something happens). So you will probably need to tie your background processing into the GUI event system.
In the event that your background processing takes a long time, you will need to break it into a number of fast chunks. At the end of each chunk, you can update a progress bar and schedule the next chunk.
This will mean you will need to probably use some state machine patterns.
Also make sure that any IO is non-blocking.
Here's an example of lengthy operation split in smaller chunks using the main loop without additional threads. Lazy Loading using the main loop.
Yes, absolutely! (in response to your title)
The GUI must be run in a separate thread. If you have ever come across those extremely annoying interfaces that lock up while an operation is in progress1, you'd know why it's very important to have the GUI always running regardless of operation happening.
It's a user experience thing.
1 I don't mean the ones that disable some buttons during operation (that's normal), but the ones that everything seems frozen.
This is the reverse: the main thread should be the Gtk one, and the long processing/computing tasks should be done in threads.
The documentation gives a clear example:
https://pygobject.readthedocs.io/en/latest/guide/threading.html

Periodically call a C function without manually creating a thread

I have implemented a WebSocket handler in C++ and I need to send ping messages once in a while. However, I don't want to start one thread per socket/one global poll thread which only calls the ping function but instead use some OS functionality to call my timer function. On Windows, there is SetTimer but that requires a working message loop (which I don't have.) On Linux there is timer_create, which looks better.
Is there some portable, low-overhead method to get a function called periodically, ideally with some custom context? I.e. something like settimer (const int millisecond, const void* context, void (*callback)(const void*))?
[Edit] Just to make this a bit clearer: I don't want to have to manage additional threads. On Windows, I guess using CreateThreadpoolTimer on the system thread pool will do the trick, but I'm curious to hear if there is a simpler solution and how to port this over to Linux.
If you are intending to go cross-platform, I would suggest you use a cross platform event library like libevent.
libev is newer, however currently has weak Win32 support.
If you use sockets, you can use select, to wait sockets events with timeout,
and in this loop calc time and call callback in suitable time.
If you are looking for a timer that will not require an additional thread, let you do your work transparently and then call the timer function at the appropriate time in the same thread by pre-emptively interrupting your application, then there is no such portable thing.
The first reason is that it's downright dangerous. That's like writing a multi-threaded application with absolutely no synchronization. The second reason is that it is extremely difficult to have good semantics in multi-threaded applications. Which thread should execute the timer callback?
If you're writing a web-socket handler, you are probably already writing a select()-based loop. If so, then you can just use select() with a short timeout and check the different connections for which you need to ping each peer.
Whenever you have asynchronous events, you should have an event loop. This doesn't need to be some system default one, like Windows' message loop. You can create your own. But you should be using it.
The whole point about event-based programming is that you are decoupling your code handling to deal with well-defined functional fragments based on these asynchronous events. Without an event loop, you are condemning yourself to interleaving code that get's input and produces output based on poorly defined "states" that are just fragments of procedural code.
Without a well-defined separation of states using an event-based design, code quickly becomes unmanageable. Because code pauses inside procedures to do input tasks, you have lifetimes of objects that will not span entire procedure scopes, and you will begin to write if (nullptr == xx) in various places that access objects created or destroyed based on events. Dispatch becomes comnbinatorially complex because you have different events expected at each input point and no abstraction.
However, simply using an event loop and dispatch to state machines, you've decreased handling complexity to basic management of handlers (O(n) handlers versus O(mn) branch statements with n types of events and m states). You decouple handling but still allow for functionality to change depending on state. But now these states are well-defined using state classes. And new states can be added if the requirements of the product change.
I'm just saying, stop trying to avoid an event loop. It's a software pattern for very important reasons, all of which have to do with producing professional, reusable, scalable code. Use Boost.ASIO or some other framework for cross platform capabilities. Don't get in the habit of doing it wrong just because you think it will be less of an effort. In the end, even if it's not a professional project that needs maintenance long term, you want to practice making your code professional so you can do something with your skills down the line.

Controlled application shut-down strategy

Our (Windows native C++) app is composed of threaded objects and managers. It is pretty well written, with a design that sees Manager objects controlling the lifecycle of their minions. Various objects dispatch and receive events; some events come from Windows, some are home-grown.
In general, we have to be very aware of thread interoperability so we use hand-rolled synchronization techniques using Win32 critical sections, semaphores and the like. However, occasionally we suffer thread deadlock during shut-down due to things like event handler re-entrancy.
Now I wonder if there is a decent app shut-down strategy we could implement to make this easier to develop for - something like every object registering for a shutdown event from a central controller and changing its execution behaviour accordingly? Is this too naive or brittle?
I would prefer strategies that don't stipulate rewriting the entire app to use Microsoft's Parallel Patterns Library or similar. ;-)
Thanks.
EDIT:
I guess I am asking for an approach to controlling object life cycles in a complex app where many threads and events are firing all the time. Giovanni's suggestion is the obvious one (hand-roll our own), but I am convinced there must be various off-the-shelf strategies or frameworks, for cleanly shutting down active objects in the correct order. For example, if you want to base your C++ app on an IoC paradigm you might use PocoCapsule instead of trying to develop your own container. Is there something similar for controlling object lifecycles in an app?
This seems like a special case of the more general question, "how do I avoid deadlocks in my multithreaded application?"
And the answer to that is, as always: make sure that any time your threads have to acquire more than one lock at a time, that they all acquire the locks in the same order, and make sure all threads release their locks in a finite amount of time. This rule applies just as much at shutdown as at any other time. Nothing less is good enough; nothing more is necessary. (See here for a relevant discussion)
As for how to best do this... the best way (if possible) is to simplify your program as much as you can, and avoid holding more than one lock at a time if you can possibly help it.
If you absolutely must hold more than one lock at a time, you must verify your program to be sure that every thread that holds multiple locks locks them in the same order. Programs like helgrind or Intel thread checker can help with this, but it often comes down to simply eyeballing the code until you've proved to yourself that it satisfies this constraint. Also, if you are able to reproduce the deadlocks easily, you can examine (using a debugger) the stack trace of each deadlocked thread, which will show where the deadlocked threads are forever-blocked at, and with that information, you can that start to figure out where the lock-ordering inconsistencies are in your code. Yes, it's a major pain, but I don't think there is any good way around it (other than avoiding holding multiple locks at once). :(
One possible general strategy would be to send an "I am shutting down" event to every manager, which would cause the managers to do one of three things (depending on how long running your event-handlers are, and how much latency you want between the user initiating shutdown, and the app actually exiting).
1) Stop accepting new events, and run the handlers for all events received before the "I am shutting down" event. To avoid deadlocks you may need to accept events that are critical to the completion of other event handlers. These could be signaled by a flag in the event or the type of the event (for example). If you have such events then you should also consider restructuring your code so that those actions are not performed through event handlers (as dependent events would be prone to deadlocks in ordinary operation too.)
2) Stop accepting new events, and discard all events that were received after the event that the handler is currently running. Similar comments about dependent events apply in this case too.
3) Interrupt the currently running event (with a function similar to boost::thread::interrupt()), and run no further events. This requires your handler code to be exception safe (which it should already be, if you care about resource leaks), and to enter interruption points at fairly regular intervals, but it leads to the minimum latency.
Of course you could mix these three strategies together, depending on the particular latency and data corruption requirements of each of your managers.
As a general method, use an atomic boolean to indicate "i am shutting down", then every thread checks this boolean before acquiring each lock, handling each event etc. Can't give a more detailed answer unless you give us a more detailed question.