Consider the following GUI:
when the user press the + button the value is incremented to 6.
However on another computer another user is running the same GUI.
The two GUIs have to stay in sync.
If one of the users press the + button the value should be updated for both GUIs.
The remote GUI, the client, communicate with the local server via a simple protocol.
The communication takes the form of a cmd sent from the client and a response sent from the server. There are two commands:
1. cmd:"GET_VALUE", response: "5"
2. cmd: "INCREMENT", response: "OK"
Unfortunately the client has to poll GET_VALUE to be notified,
but the protocol albeit flawed can not be changed.
How can I implement this in Qt, C++?
So far I have come up with the following classes (rough outline):
class Model {
public:
std::atomic<int> m_value;
};
class Widget : public QWidget {
public slots:
void incrementClickedLocally(); // must update Model::m_value somehow
void valueChangedFromModel(int value); // will update the QLineEdit
};
// Reads synchronously from TCP/IP using WinSocket and works on the Model
class RemoteHandler : public QThread {
private:
void run override();
};
I would like to use signals/slots to communicate across the threads.
However it seems that the RemoteHandler can not use signal/slots to get the Model::m_value since slots can not have return types?
Further it would be convenient to emit a valueChanged signal from Model to notify Widget. However in order to do that Model must be a QObject.
It seems that when Model becomes a QObject there are many potential thread problems I have to look out for?
As it is Model is threadsafe. I can therefore request Model::m_value directly from the non main thread in RemoteHandler while the Widget may be accessing the same variable simultaneously from the main thread.
It cannot work with those commands.
The logic is well-known from the design of multi-core CPU's. You need Compare-and-Swap (CAS), Load-Link/Store Conditional (LL/SC) or something equally powerful. With the weak protocol you have, it can be proven that the race conditions are unsolvable.
Related
I'm trying to implement an application in Qt with a model-view-controller scheme. I have some model classes (databases), one application controller, and a bunch of GUI classes. All GUI classes know the app controller and can call its public slots to send data to it that should be stored in the model. The app controller takes the data and calls the appropriate database to store it. The database classes check the data and return a bool to the app controller to tell if the data was okay or not.
Now, one GUI element has prepared some user data and wants to send it to the app controller. I am trying to figure out how to let the GUI-class know that the app controller validated the incoming data with the model and it accepted the data. My app controller shouldn't care nor know which GUI elements call its public API to commit data to the model. But how does the app controller communicate a response to the GUI element to tell it, that everything was fine, so the GUI element can close itself?
My idea would have been to let the GUI element create a random number token to send it to the app controller together with the data as a kind of "callback address". As soon as my GUI element receives an okay signal with the correct token attached, it can react to that.
I was dunno. All my solutions feel weird and not how it's supposed to be in Qt.
Edit 1: a pseudo-code example for clarification:
void Appcontroller::Slot(userdata)
{
bool okay = database->save(userdata)
};
void Appcontroller::CreateMasterWindow()
{
this->masterwindow_ = new MasterWindow(this);
// I am propagating the knowledge of the app controller to the
// MasterWindow and the latter can propagate that info further
// down, that's fine (everybody can know the responsible
// controller, but I don't think the controller should care about
// all his bastard children)
};
void MasterWindow::CreateSubWindow()
{
this->subwindow_ = new SubWindow(appcontroller_);
// the masterwindow creates a random subwindow that the controller
// should't have to care about
};
void SubWindow::SendUserData(userdata)
{
QObject::connect(this, &SubWindow::SendToControllerSignal,
appcontroller_, &Appcontroller::Slot);
emit SendToControllerSignal(userdata);
// how to get a callback (targeted to me/this) from this,
// if the appcontroller does not know me? what is de way?
};
TL;DR: Connections should be made outside of the components. To compose the parts of your system, you instantiate the objects, and then connect them for desired functionality. The objects should otherwise have no knowledge of each other.
Thus, the only means of communication between the objects are signals and slots.
All GUI classes know the app controller and can call its public slots to send data to it that should be stored in the model
Nope.
The GUI classes should know nothing. When a GUI class needs something, it emits a signal. When a GUI class is supposed act on something (e.g. a change in the model), it exposes that as a slot.
I am propagating the knowledge of the app controller to the MasterWindow
Why? The MasterWindow exposes its functionality via signals and slots. Composing it into a bigger system is accomplished by signal/slot connections. No other knowledge is needed.
The app controller takes the data and calls the appropriate database to store it.
Does there even need to be a controller? All it seems to do is act like a signal-slot connection. You can directly connect the GUI classes to the database, and the controller could be what sets the connections up initially.
Otherwise, the application controller can act as a viewmodel, i.e. a QAbstractItemModel that adapts the model exposed by the database, and tweaks it for display/interaction (e.g. adds color properties, icons, etc.).
The database classes check the data and return a bool to the app controller to tell if the data was okay or not.
The database classes should expose slots that are used to modify the database state. They should also expose signals that indicate any changes. To indicate failure, the database can indicate a "change" with the same value.
how to get a callback (targeted to me/this) from this, if the appcontroller does not know me? what is de way?
The signals from the model/database are connected to the GUI classes. A GUI class can go into a "change pending" state once it emits a "change requested" signal. It will then react accordingly when its "new value" slot is called with the updated value: if the value didn't change, it indicates a failure, otherwise it indicates success. If it didn't request a change, it simply updates the displayed value - something else changed it.
This can be all done using nothing more than the Q_PROPERTY mechanism, and the change notification signals.
If the values aren't simple discretes, but rather have some structure, expose those as indices in a custom QAbstractItemModel. Each GUI item can then act on one or more model indices: requesting the changes, and reacting to value updates.
Multiple GUI elements can be hooked up to the same database variable (or no GUI elements!), and the GUI must support this and update its state to reflect the state of the model.
The "tickets" or "request identifiers" you propose are mostly spurious. The requesting GUI element has enough state to know that it requested a change, and can always act predictably on subsequent feedback from the model/database.
My first naive at updating my progress bar was to include the following lines in my loop which is doing the processing, making something like this:
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
//Added these lines but they don't do anything
ui->progressBar->setValue(numberProcessed++);
ui->progressBar->repaint();
}
I thought adding the repaint() would make the execution pause while it updated the GUI, but apparently it's not that simple. After looking at the questions:
QProgressBar Error
Progress bar is not showing progress
it looks like I'm going to have to put the data processing in a different thread and then connect a signal from the data processing thread to the GUI thread to update the progressbar. I'm rather inexperienced with GUIs and threads and I was wondering if anyone could just point me in the right direction, ie what Qt classes should I be looking at using for this. I'd guess I need a QThread object but I've been looking through the QProgressBar documentation but it doesn't bring up the topic of threading.
As #rjh and #Georg have pointed out, there are essentially two different options:
Force processing of events using QApplication::processEvents(), OR
Create a thread that emits signals that can be used to update the progress bar
If you're doing any non-trivial processing, I'd recommend moving the processing to a thread.
The most important thing to know about threads is that except for the main GUI thread (which you don't start nor create), you can never update the GUI directly from within a thread.
The last parameter of QObject::connect() is a Qt::ConnectionType enum that by default takes into consideration whether threads are involved.
Thus, you should be able to create a simple subclass of QThread that does the processing:
class DataProcessingThread : public QThread
{
public:
void run();
signals:
void percentageComplete(int);
};
void MyThread::run()
{
while(data.hasMoreItems())
{
doSomeProcessing(data.nextItem())
emit percentageCompleted(computePercentageCompleted());
}
}
And then somewhere in your GUI code:
DataProcessingThread dataProcessor(/*data*/);
connect(dataProcessor, SIGNAL(percentageCompleted(int)), progressBar, SLOT(setValue(int));
dataProcessor.start();
You need to call QApplication::processEvents() periodically inside your processing loop to let it handle UI events.
As Georg says, Qt is a single-threaded co-operative multitasking environment. You get full control of your process until you relinquish it voluntarily with processEvents() - until you do that, Qt can't update the UI elements, handle async HTTP requests, handle input, or pretty much anything else. It's up to you to make sure that stuff gets a timeslice while you're in a long processing loop.
You can create a sub-class of QThread that emits a signal progressChanged, which you connect to the QProgressBar.
connect() makes the connections auto connections per default. That means that the signal-slot-mechanism already takes care of the threading issues for you, so you don't need to worry about that.
Under Qt 4.7.1, Qt Creator 2.1.0, OS X 10.6.8:
I have a QLabel in the mainwindow ui, which uses Courier New / 13, with room for four lines of text.
I create four lines of text, considerably shorter than the label is horizontally, of the general format:
"my text\r\n"
I filter the text before sending it along. The only characters in the cstring will be 0x0D, 0x0A, 0x20 (space) and from there up to lower case z (0x7A') and of course the terminating zero. No other control characters - if they are received from the source, I replace them with '*'
I send the four lines of text to the QLabel as a single zero-terminated cstring via setText()
I sometimes do this at a fairly high rate, several times a second at least -- this is RDBS data from an FM station so it changes in real time:
qDebug() << rbl; // data keeps coming to console
ui->fourLineLabel->setText(rbl); // add this, display soon stops updating
This works. For a while. Then the display stops updating. This is the area at issue:
(source: fyngyrz.com)
If I leave everything else in, but take out the setText(), the problem does not occur.
I know that for some things, Qt wants painting to be done within a paint event. Is this also true of a setText() ?
Reading the docs on qt widgets, it says that widgets do their own painting within their own paint event... but the behavior here is very similar to the kind of malfappery that goes on when one actually tries to use a painter outside of a paint event. And it's definitely related to that setText(), so... mumble.
As I write this, the application has been running for hours without any display lockup, outputting the same text to the console via qDebug(). It takes about 5 minutes for the problem to occur if I uncomment the setText(). It's 100% repeatable.
Is there something I should be doing that I'm not doing, paint-wise or similar?
Thanks for any assistance.
In general you should not update Qt controls from non UI thread, only a small amount of things is allowed to do regarding a painting in non UI thread - http://doc.qt.io/qt-4.8/threads-modules.html
If you need to update UI from non UI thread - use signals and slots (QueuedConnection or BlockingQueuedConnection connections, though make sure to not create deadlock with BlockingQueuedConnection). Or if you don't want to create additional signals and slots for some easy update - use invokeMethod (it can even return value and if you use it with BlockingQueuedConnection connection type, your thread will wait until UI is updated).
And a general advice - if you have a possibility - make one call for bulk of updates to UI instead of few small calls.
It is always advised that the GUI thread interfaces with all other objects through the signal-slot mechanism. In fact, no direct calls from and to the main thread are to be made. In that manner the GUI will be responsive, and we don't end up waiting for it to come back. Certainly polling solutions are not ideal, and should be avoided as they end up using cup resources without reason.
If one is using only QThread type threads then updating the GUI should be done by using the signal-slot mechanism. When events of data presented need to be serialized using the Qt::QueuedConnection is sufficient. In your case that is true.
If not using that , then signals may not be processed in the sequence emitted. Qt::BlockingQueuedConnection should be used only when we want to restrict the caller continue from processing before the slot on the receiver has completed. This is very rarely the case for processing that happens on the GUI thread.
Special care has to be taken when we want to connect from a non-qt thread, e.g. An std thread, because the objects created e.g. in a native thread will not be known on the receiver end.
One way to update the ui from a non-ui thread is to serialize and copy your messages. Do the following (works even for non-QThreads e.g. boost::thread ):
Setup a singleton QObject that provides public methods to force-emit
signals containing the data that you want to send ,e.g. a singleton
Setup slots in objects that only accept arguments by value
Connect the signals to the slots in an object within the ui-thread
Connections must be Qt::QueuedConnection
class timer : public QObject
{
Q_OBJECT
//... write a singleton here
std::mutex mut;
public signals:
signal_tic(QString const );
public:
void force_emit_tic(QString const s )
{
std::lock_guard<std::mutex> l(mut);
emit signal_tic(s);
}
timer & ref()
{
static timer This;
return This;
}
private:
timer(){}
};
// in a main thread object setup this connection
connect(&timer::ref(),SIGNAL(signal_tic(Qstring
const)),this,SLOT(slot_accept_tic(QString const ), Qt::QueuedConnection)
// In any other thread
timer::ref()::force_emit_tic( string_when_this_happened )
Calling directly the singleton force-emit method results in the desired behaviour. (ofcourse objects must be properly copiable for this to work)
The reason for sending by value is that if you pass a const reference to temporary residing in another thread it's lifetime is not guaranteed. Furthermore, you need to take care of serializing the messages to the ui-thread before they actually arrive or you will eventually receive one of either incosistent data or a SIGSEGV. Qt::QueuedConnection guarantees that connections are serialized only within the memory space known to QThreads.
I have something like the following design of classes and I'm wondering if it's OK that I use many signal slot connections to communicate between them. There is a MainWindow class which holds all the GUI, then a Wrapper class, which provides an interface to the back-end, then there is a Controller class for spawning and managing threads and finally there are Workers which do all the work.
Now let's say I'm loading a file and want to display progress using a progress bar in the MainWindow. My Worker class sends updateProgress(int progress) to Controller::handleProgress(int progress) slot which again sends progress signal to the Wrapper class, which in return sends a progress signal to the main window, which finally updates the progress bar.
Similarly when the data has been loaded it is processed in the Wrapper class and, again, communicated through signals and slots (although with one less step).
Is it a standard way of doing things in Qt or should I rethink my design?
It is a valid possibility.
Note that Qt allows you to go even further and do the following:
QObject::connect(&sender, SIGNAL(mySenderSignal(int)),
&receiver, SIGNAL(myReceiverSignal(int));
That's right, you can bind a signal to a signal. All it does can be seen as "when the sender's signal is emitted, emit the receiver's signal".
If you don't have any specific task to perform in your intermediary slots, that might save you a few lines, while showing exactly what you're doing: you're "forwarding" a signal. Otherwise, if you must absolutely do work in between, then you must keep the signals and the slots.
Note that you still have to be sure that the signals signatures match.
I am new on Qt programming. I have to make some computations which take long time. I use an edit box and two button named as "start" and "stop". The edit box is used for the initialization. Start button starts the computation. While the computation is going on, I must be able to stop the computation whenever I want. But when I start the computation by clicking the start button. As expected, I cannot click any component on the window until the computation is completed.
I want to use the components (especially stop button) on the window normally while the computation is performing. But I am not good on the threads, I am looking for an easier method. Is there any simple solution?
There are a couple of options.
1. Subclass QRunnable
Subclass QRunnable and use QThreadPool to run it in a separate thread. To communicate with the UI, use signals. Example of this:
class LongTask: public QRunnable
{
void run()
{
// long running task
}
};
QThreadPool::globalInstance()->start(new LongTask);
Note that you don't need to worry about managing the thread or the lifetime of your QRunnable. For communicating, you can connect your custom signals before starting the QRunnable.
2. Use QtConcurrent::run
This is a different approach and might not suit your problem. Basically, the way it works is the following: you get a handle to the future return value of the long task. When you try to retrieve the return value, it will either give it to you immediately or wait for the task to finish if it hasn't already. Example:
QFuture<int> future = QtConcurrent::run(longProcessing, param1, param2);
// later, perhaps in a different function:
int result = future.result();
3. Subclass QThread
You probably don't need this, but it isn't hard either. This one is very similar to #1 but you need to manage the thread yourself. Example:
class MyThread : public QThread
{
public:
void run()
{
// long running task
}
};
QThread* thread = new MyThread(this); // this might be your UI or something in the QObject tree for easier resource management
thread.start();
Similarly to QRunnable, you can use signals to talk to the UI.
In your computation you can put QCoreApplication::processEvents(); so that GUI events also get processed. This will omit usage of threads.
You can have your computation occur in a different thread than your GUI. When the GUI recieves a signal that the stop button is pressed, you change a flag value which your computation thread periodically checks. When the flag is set, you can terminate the computation thread.
Either use threads (perhaps synchronizing them by sending messages on pipes to self), or use timer (with a 0 millisecond delays, this is how idle processing is done in Qt).