Multi-threading design along with an undo/redo stack - c++

I have this call stack to perform a heavy computation:
// QML
StyledButton {
onButtonClicked: {
registeredCppClass.undoHandler.createCommand()
}
}
void UndoHandler::createCommand()
{
m_undoStack->push(new Command());
}
class Command : public QUndoCommand
{
public:
Command();
virtual ~Command();
virtual void undo();
virtual void redo();
// ...
private:
// Handler does the logic
LogicHandler *m_logicHandler;
// Output by logic handler
QString m_outputName;
};
void Command::redo()
{
if (/* */) {
} else {
// Run heavy computation
m_outputName = m_logicHandler->run();
}
}
QString LogicHandler::run()
{
// Heavy computation starts
}
Intention
I intend to implement QThread by this approach to prevent GUI from getting non-responsive while heavy computation is being done. But I don't know where QThread and Worker class need to be implemented. Should they be within:
UndoHandler::createCommand
Command::redo
LogicHandler::run
... ?
What is the best location for QThread and Worker considering their signal-slot connections?

The general advice is to never read QThread documentation. Follow that up with never read Linux thread documentation. I say this as someone who has written quite a few books on software development.
The long answer is threading wasn't well thought out early on and there is a lot of, now bad, information out there. During Qt 3.x and I believe early Qt 4.x one was supposed to derive a class from QThread and override the run(). You can imagine just how well that worked for newbie developers unfamiliar with threads in general and unable to design in mutex or other access protection when manipulating things in multiple threads.
Your design makes it appear you have read some of this documentation. It's still floating around out there.
At some point during Qt 4.x we were no longer supposed to derive from QThread. Instead we were supposed to just create a QThread and moveToThread(). Kinda sorta worked but you could still end up with "dangling threads" if your program didn't follow the happy path through the code.
Around the same time, at least as far as my exposure, we also got a global thread pool.
Your design is really flawed because you looked at old doc. Not your fault. The old doc tends to turn up first in searches.
Visit this GitHub repo and pull down the project. The only dev_doc setup documentation I have completed is for Fedora. I will be working on Ubuntu this morning if I don't get interrupted. Be sure to check out the diamond-themes branch.
Yes, this is using CopperSpice, but CopperSpice is a fork of Qt 4.8 and this is the only concrete code example I could think of off the top of my head. You can build and run the editor or you can poke-and-hope by reading advfind_busy.cpp. What you are looking for is how QFuture is used. That source file is only about 200 lines long and it has a short header file.
Throw out your current design. You need QFuture and QtConcurrent::run().
Note: The header files for these things are different in name and location when compared to current Qt 5.x. That much you will need to look up if you choose to stay with Qt. How you use this stuff is not.
Note 2: If you don't have some kind of throttle control to limit each of these tasks to a single thread instance you will need to dynamically create and destroy QFuture objects. This means you have to have some kind of list or vector keeping track of them and your object destructor needs to walk that list killing off the threads and deleting the objects.
If you want to go on a journey setting up CopperSpice on Ubuntu it is spread across a multi-part blog post starting here.

IMHO, your intentions are correct, and you are headed in the right direction (leaving aside the argument for using QtConcurrency -- thread pools and futures -- since that's not pertinent to the immediate question). Let's address the first part: the objects and execution flow.
As the classes have been outlined in the code snippets, you will need to take extra care to correctly push them across thread boundaries. If you think for a moment, the worker object is created in the calling thread, therefore some of the object's members will also be created in the calling thread. For members which are pointers, this does not pose much of a problem, because you may elect to delay the creation of those objects until after the enclosing object instance has been created and moved to the worker thread. But, embedded objects are created when the object is constructed. If the embedded object derives from QObject, it will have its thread affinity set to the caller thread. In such a case, signals won't work properly. To alleviate this problem, it is often easiest to pass the work thread to the worker object's constructor, so the worker object is able to move all of its embedded objects to the worker thread.
Second, assuming the following:
Command holds a unique instance of LogicHandler, and
LogicHandler does not have state, and
LogicHandler is a subclass of QObject, and
LogicHandler is the worker class
My advice would be to place the spinning up of the thread in Command::redo, then connect the signals similar to advice given at the bottom of this article. Also, you would not set Command.m_outputName to the return value of LogicHandler::run. LogicHandler::run should return void. Instead, you should add a signal to LogicHandler that emits the string value when it has finished processing; then, add a slot in Command to handle that. A QString can easily be marshaled across thread boundaries (make sure you make the connections of the proper type, see here).
The connecting of the worker startup method, to the threads started signal gets the execution started. There is no need to inherit from QThread and override run. The worker should also emit a finished signal, that should be connected to the thread's quit slot. The worker's finished signal should also be connected to both the thread's and worker's deleteLater slot. When these are setup, just call the thread's start method.
From there, the execution will return from redo, and you will be notified that the worker is finished when it emits a signal (the one I mentioned that you will need to add) and passes the output string. If the lifetime of the worker is different (I'm guessing longer, since you need to spin up a thread to do long operation) from the instance of Command, then you will need to connected the return value signal from the worker object to a different object.

Related

Custom creation of QFuture

I've faced quite an odd problem with QtConcurrent, mostly because of strange programming desires, maybe it's just an XY-problem, but...
So, there is my code, trying to communicate with the database, a backend code actually (on Qt, yes). It has to work quick and handle some requests, so I need a thread pool. As a well-known fact I suppose the connection establishing itself is a very time-consuming operation, so there is a need in persistent database connections resulting in persistent threads (QSqlDatabase cannot be moved around between the threads). Also it is quite natural to want asynchronous request handling, thus resulting in some need of a simple way to pass them to the persistent threads.
Nothing too complex, lets assume there already exists some boilerplate in a form like...
// That's what I want for now
QFuture<int> res = workers[i]->async(param1, param2);
// OR
// That's what I DO NOT want to get
workers[i]->async(param1, param2, [](QFuture<int> res) { // QFuture to pass exceptions
// callback here
});
That can be done for sure. Why not std::future? Well, it is much easier to use QFutureWatcher and it's signals for notifications about result's readiness. Pure C++ notification solutions are muuuch more complex and callbacks are also someting that has to be dragged through the class hierarchy. Each worker interfaces a thread with DB connections, obviously.
Okay, all of that can be written, but... custom thread pool would mean no QtConcurrent convenience, there seem to be only risky ways to create that QFuture so that it could be returned by the custom worker. QThreadPool is of no use, because it would be a whole big story to create persistent runnables in it. More to say, the boilerplate I've briefly described is gonna be some kind of project's core, used in many places, not something to be easily replaced by a 100 hand-made thread managings.
In short: if I could construst a QFuture for my results, the problem would be solved.
Could anyone point me to a solution or a workaround? Would be grateful for any bright ideas.
UPD:
#VladimirBershov offered a good modern solution which implements observer pattern. After some googling I've found a QPromise library. Of course, constructing a custom QFuture is still hacky and can be only done via undocumented QFutureInterface class, but still some "promise-like" solution makes asynchronous calls neater by far as I can judge.
You can use AsyncFuture library as a custom QFuture creation tool or ideas source:
AsyncFuture - Use QFuture like a Promise object
QFuture is used together with QtConcurrent to represent the result of
an asynchronous computation. It is a powerful component for
multi-thread programming. But its usage is limited to the result of
threads, it doesn't work with the asynchronous signal emitted by
QObject. And it is a bit trouble to setup the listener function via
QFutureWatcher.
AsyncFuture is designed to enhance the function to offer a better way
to use it for asynchronous programming. It provides a Promise object
like interface. This project is inspired by AsynQt and RxCpp.
Features:
Convert a signal from QObject into a QFuture object
Combine multiple futures with different type into a single future object
Use Future like a Promise object
Chainable Callback - Advanced multi-threading programming model
Convert a signal from QObject into a QFuture object:
#include "asyncfuture.h"
using namespace AsyncFuture;
// Convert a signal from QObject into a QFuture object
QFuture<void> future = observe(timer, &QTimer::timeout).future();
/* Listen from the future without using QFutureWatcher<T>*/
observe(future).subscribe([]() {
// onCompleted. It is invoked when the observed future is finished successfully
qDebug() << "onCompleted";
},[]() {
// onCanceled
qDebug() << "onCancel";
});
My idea is to use thread pools with maximum 1 thread available for each.
QThreadPool* persistentThread = new QThreadPool; // no need to write custom thread pool
persistentThread->setMaxThreadCount(1);
persistentThread->setExpiryTimeout(-1);
and then
QFuture<int> future_1 = QtConcurrent::run(persistentThread, func_1);
QFuture<int> future_2 = QtConcurrent::run(persistentThread, func_2);
func_2 will be executed after func_1 in the same one "persistent" thread.

How to stop a qThread in QT [duplicate]

This question already has an answer here:
Qt, How to pause QThread immediately
(1 answer)
Closed 5 years ago.
I would like to know how to properly stop a QThread. I havea infinite loop in a thread, and I would like to stop it when I do a specific action :
I have tried :
if (thread->isRunning()){
worker->stop();
thread->terminate();
}
the stop() method set a value to false to go out of my infinite loop.
Furthermore, I don't really understand the difference between quit(), terminate() or wait(). Can someone explain me ?
Thanks.
A proper answer depends on how you actually use QThread and how you've implemented stop().
An intended use case in Qt assumes following model:
You create an object that will do some useful work in response to Signals
You create a `QThread` and move your object to this thread
When you send a signal to your object, it's processed in `QThread` you've created
Now you need to understand some internals of how this is actually implemented. There are several "models" of signals in Qt and in some cases when you "send a signal" you effectively simply call a "slot" function. That's a "direct" slot connection and in this case slot() will be executed in caller thread, one that raised a signal. So in order to communicate with another thread, Qt allows another kind of signals, queued connections. Instead of calling a slot(), caller leaves a message to object that owns this slot. A thread associated with this object will read this message (at some time later) & perform execution of slot() itself.
Now you can understand what's happening when you create and execute QThread. A newly created thread will execute QThread::run() that, by default, will execute QThread::exec() which is nothing, but an infinite loop that looks for messages for objects associated with thread and transfers them to slots of these objects. Calling QThread::quit() posts a termination message to this queue. When QThread::exec() will read it, it will stop further processing of events, exit infinite loop and gently terminate the thread.
Now, as you may guess, in order to receive termination message, two conditions must be met:
You should be running `QThread::exec()`
You should exit from slot that is currently running
The first one is typically violated when people subclass from QThread and override QThread::run with their own code. In most cases this is a wrong usage, but it's still very widely taught and used. In your case it seems that you're violating the second requirement: your code runs infinite loop and therefore QThread::exec() simply doesn't get a control and don't have any chance to check that it needs to exit. Drop that infinite loop of yours to recycle bin, QThread::exec() is already running such loop for you. Think how to re-write your code so it does not running infinite loops, it's always possible. Think about your program in terms of "messages-to-thread" concept. If you're checking something periodically, create a QTimer that will send messages to your object and implement a check in your slot. If you processing some large amount of data, split this data to smaller chunks and write your object so it will process one chunk at a time in response to some message. E.g. if you are processing image line-by-line, make a slot processLine(int line) and send a sequence of signals "0, 1, 2... height-1" to that slot. Note that you will also have to explicitly call QThread::quit() once done processing because event loop is infinite, it doesn't "know" when you processed all the lines of your image. Also consider using QtConcurrent for computationally-intensive tasks instead of QThread.
Now, the QThread::terminate() does stop a thread in a very different manner. It simply asks OS to kill your thread. And OS will simply abruptly stop your thread at arbitrary position in the code. Thread stack memory will be free'd, but any memory this stack pointed to won't. If a thread was owning some resource (such as file or mutex), it won't ever release it. An operation that involve writing data to memory can be stopped in the middle and leave memory block (e.g. object) incompletely filled and in invalid state. As you might guess from this description, you should never, ever call ::terminate() except for very rare cases where keeping running of thread is worse than getting memory & resource leaks.
QThread::wait() is just a convenience function that waits until QThread ceases to execute. It will work both with exit() and terminate().
You can also implement a threading system of your own subclassed from QThread and implement your own thread termination procedure. All you need to exit a thread is, essentially, just to return from QThread::run() when it becomes necessary and you can't use neither exit() nor terminate() for that purpose. Create your own synchronization primitive and use it to signal your code to return. But in most cases it's not a good idea, keep in mind that (unless you work with QEventLoop by yourself), Qt signal and slots won't be working properly in that case.

Why is this QObject subclass created in a different thread than its parent?

I'm running into some Qt threading issues that I don't understand, running Qt5.6 on Windows 7. Everything is installed and built using MSYS2.
I've created a Server object, which manages a Device object on behalf of remote clients. Both are subclasses of QObject. After the Server receives a client request to create a device, the Device is constructed with the Server as its parent.
But when I run the application in GDB, calling this->parent() for the Device returns a NULL pointer, indicating that this object has no parent. Furthermore, this->thread() returns a different thread from the Server object's thread. And the requisite "Cannot create children for a parent that is in a different thread" warning is printed, somewhere in the QObject constructor itself.
This is despite the Device object's constructor being passed the Server as its parent and there being no other explicitly-created threads. There are no explicitly-created QThread objects, and I'm only using the default event loop created by QCoreApplication::exec(). Furthermore, compiling and running this on either Linux or OS X confirms that the parent is set correctly and that both objects live in the same thread.
I understand why a call like setParent() or its moral equivalent will fail, to keep objects and their corresponding event loops in the same thread. But it appears that the thread affinity for the Device object is somehow already set by the time the constructor is called. But why is there more than one thread in the first place? And why only on Windows? And why would the object be created in a seemingly random thread, when it could very well use the thread of the parent that I'm passing in the constructor?
EDIT:
A couple of other things to note. I am not only not calling moveToThread() or anything like that, but there's no concurrency of any kind. This includes things like QRunnable or anything from the QtConcurrent module.
Another thing that actually solves the practical problem, but that I don't understand, is that this goes away if I compile for release. I've been using the debug build during development, which is apparently the only time the strange thread/parent behavior manifests. When I run the release build, everything works swimmingly. Is it possible this is a bug in the MSYS2 build of GDB that I'm using? Maybe there's some way in which Qt is not playing nicely with GDB (or vice versa)?
EDIT 2:
Based on a comment from #Ben, I dug around in more depth in the QObject constructor code (found here which starts on line 821. On line 826, ultimately the function QThreadData::current() is called, and this is where the threads of the parent and child first seem to differ. The Qt internal class QThreadData's static function current() (found here) seems to query thread-local storage to return the current thread's index, I think, which appears different from that of the parent's thread. I don't know enough about the Windows threading libraries to know if this is really what's going on, but after reading the pthread-based version of the code, that's my best guess.
I'm pretty far down the rabbit hole at this point, but it seems like my amended question is: Why does QThreadData::current() return a different thread from the parent? Or why has the thread-local storage containing this data changed between the time the parent was constructed and the child's constructor is called?

Singleton class across the whole project approach

I have a singleton class for logging purpose in my Qt project. In each class except the singleton one, there is a pointer point to the singleton object and a signal connected to an writing slot in the singleton object. Whichever class wants to write log info just emit that signal. The signals are queued so it's thread-safe.
Please critique this approach from OOP point of view, thanks.
=============================================================================================
Edit 1:
Thank you all your applies, listening to opposite opinions is always a big learning.
Let me explain more about my approach and what I did in my code so far:
Exactly as MikeMB pointer, the singleton class has a static function like get_instance() that returns a reference to that singleton. I stored it in a local pointer in each class's constructor, so it will be destroyed after the constructor returns. It is convenient for checking if I got a null pointer and makes the code more readable. I don't like something as this:
if(mySingletonClass::gerInstance() == NULL) { ... }
connect(gerInstance(), SIGNAL(write(QString)), this, SLOT(write(QString)));
because it is more expensive than this:
QPointer<mySingletonClass> singletonInstance = mySingletonClass::getInstance();
if(singletonInstance.isNull) { ... }
connect(singletonInstance, SIGNAL(write(QString)), this, SLOT(write(QString)));
Calling a function twice is more expensive than creating a local variable from ASM's point of view because of push, pop and return address calculation.
Here is my singleton class:
class CSuperLog : public QObject
{
Q_OBJECT
public:
// This static function creates its instance on the first call
// and returns it's own instance just created
// It only returns its own instance on the later calls
static QPointer<CSuperLog> getInstance(void); //
~CSuperLog();
public slots:
void writingLog(QString aline);
private:
static bool ready;
static bool instanceFlag;
static bool initSuccess;
static QPointer<CSuperLog> ptrInstance;
QTextStream * stream;
QFile * oFile;
QString logFile;
explicit CSuperLog(QObject *parent = 0);
};
I call getInstance() at the beginning of main() so make sure it is read immediately for each other class whenever they need to log important information.
MikeMB:
Your approach is making a middle man sitting in between, it makes the path of the logging info much longer because the signals in Qt are always queued except you make direct connection. The reason why I can't make direct connection here is it make the class non-thread-safe since I use threads in each other classes. Yes, someone will say you can use Mutex, but mutex also creates a queue when more than one thread competing on the same resource. Why don't you use the existing mechanism in Qt instead of making your own?
Thank you all of your posts!
=========================================================
Edit 2:
To Marcel Blanck:
I like your approach as well because you considered resource competition.
Almost in every class, I need signals and slots, so I need QObject, and this is why I choose Qt.
There should be only one instance for one static object, if I didn't get it wrong.
Using semaphores is same as using signals/slots in Qt, both generates message queue.
There always be pros and cons regarding the software design pattern and the application performance. Adding more layers in between makes your code more flexible, but decreases the performance significantly on those lower-configured hardware, making your application depending one most powerful hardware, and that's why most of modern OSes are written in pure C and ASM. How to balance them is really a big challenge.
Could you please explain a little bit more about your static Logger factory approach? Thanks.
I do not like singletons so much because it is always unclean to use them. I have even read job descriptions that say "Knowledge of design patterns while knowing that Singleton isn't one to use". Singleton leads to dependecy hell and if you ever want to change to a completely different logging approach (mabe for testing or production), while not destroying the old one you, need to change a lot.
Another problem with the approch is the usage of signals. Yes get thread savety for free, and do not interrupt the code execution so much but...
Every object you log from needs to be a QObject
If you hunt crashes your last logs will not be printed because the logger had no time to do it before the program crashed.
I would print directly. Maybe you can have a static Logger factory that returns a logger so you can have one logger object in every thread (memory impact will still be very small). Or you have one that is threadsave using semaphores and has a static interface. In both cases the logger should be used via an interface to be more flexible later.
Also make sure that your approach prints directly. Even printf writes to a buffer before being printed and you need to flush it every time or you might never find crashes under bad circumstances, if hunting for them.
Just my 2 cents.
I would consider separating the fact that a logger should be unique, and how the other classes get an instance of the logger class.
Creating and obtaining an instance of the logger could be handled in some sort of factory that internally encapsulates its construction and makes only one instance if need be.
Then, the way that the other classes get an instance of the logger could be handled via Dependency injection or by a static method defined on the aforementioned factory. Using dependency injection, you create the logger first, then inject it into the other classes once created.
A singleton usually has a static function like get_instance() that returns a reference to that singleton, so you don't need to store a pointer to the singleton in every object.
Furthermore it makes no sense, to let each object connect its log signal to the logging slot of the logging object itself, because that makes each and every class in your project dependent on your logging class. Instead, let a class just emit the signal with the log information and establish the connection somewhere central on a higher level (e.g. when setting up your system in the main function). So your other classes don't have to know who is listening (if at all) and you can easily modify or replace your logging class and mechanism.
Btw.: There are already pretty advanced logging libraries out there, so you should find out if you can use one of them or at least, how they are used and adapt that concept to your needs.
==========================
EDIT 1 (response to EDIT 1 of QtFan):
Sorry, apparently I miss understood you because I thought the pointer would be a class member and not only a local variable in the constructor which is of course fine.
Let me also clarify what I meant by making the connection on a higher level:
This was solely aimed at where you make the connection - i.e. where you put the line
connect(gerInstance(), SIGNAL(write(QString)), this, SLOT(write(QString)));
I was suggesting to put this somewhere outside the class e.g. into the main function. So the pseudo code would look something like this:
void main() {
create Thread1
create Thread2
create Thread3
create Logger
connect Thread1 signal to Logger slot
connect Thread2 signal to Logger slot
connect Thread3 signal to Logger slot
run Thread1
run Thread2
run Thread3
}
This has the advantage that your classes don't have to be aware of the kind of logger you are using and whether there is only one or multiple or no one at all. I think the whole idea about signals and slots is that the emitting object doesn't need to know where its signals are processed and the receiving class doesn't have to know where the signals are coming from.
Of course, this is only feasible, if you don't create your objects / threads dynamically during the program's run time. It also doesn't work, if you want to log during the creation of your objects.

Calling a QObject function from QML across threads

I'm trying to determine how calling QObject slots or Q_INVOKABLE methods from QML for a QObject that lives in another thread works, and whether or not its safe to do so.
Assume there's a MainThread and ThreadA. QObjectA lives in ThreadA. The QML engine/gui/everything lives in the MainThread. I expose QObjectA to the QML engine using
declarativeView->setContextProperty("someObj",ObjectA)
Now in a QML file, I call
someObj.someMethod();
Where someMethod is a slot or is Q_INVOKABLE. I'd like to know which thread actually executes the function. If it's MainThread, that would be a bad thing, and calling a method like that across threads would be dangerous. If it was executed by ThreadA however, all would be well.
Based on this documentation: http://doc.qt.nokia.com/4.7-snapshot/qtbinding.html, I'm assuming that QMetaObject::invokeMethod() is used to call the QObject function. That documentation (http://doc.qt.nokia.com/4.7-snapshot/qmetaobject.html#invokeMethod), shows that there are different connection types available, just like with Qt signals and slots.
I'd like to know if Qt's qml engine automagically chooses the right type for the situation when invoking C++ methods from QML across threads, and if so, calling methods for objects that live in other threads from QML is an acceptable practice.
As it became apparent a while ago, QML doesn't seem to be able to go across threads.
So one needs to implement a C++ side intermediate object that lives in the main thread to dispatch calls to objects in other threads.
QML object -> object in a different thread // doesn't work!!!
QML object -> C++ mediator object -> object in a different thread // WORKS!!!
Basically, "transcending" threads must happen in C++ entirely, thus the need of a mediator object.
I guess the someMethod will be executed in ThreadA since the object lives in that thread.
But normally if this gives a problem, then I would do something like this.
connect(&threadA, SIGNAL(started()), someObj, SLOT(someMethod());
But to start that ThreadA we need one more CppObject to link QML and CPP.
You can use this->thread(); or QThread::currentThreadId(); inside the slot to get the thread the slot is working in. It will always be the thread, the ObjectA was created in (if there was no moveToThread()).
The Qt-Engine will select the right Qt:ConnectionType by determine call and called thread.
Extra tip: You can use GammaRay or ThreadSanitizer to see current direct connections across threads.
QML logic is event-driven and all invokes are parts of JavaScript functions. JS functions may be event handlers (for ex. UI event handlers) or may be invoked somewhere in C++ code if you wrap them in QScript object. Also you can invoke them in JavaScript WorkerTherad. That is why only you can provide an answer, where does someObj.someMethod() invokation take place.