I have a thread for a connection UDP.
I want to pause my thread while timeout (or while there isn't new frames in my QStack which stores UDP frames).
run(){
forever{
QTimer *timer_nb = new QTimer();
timer_nb->start(500);
// --- Wait for timeout or new frames in my QStack
//then ....
}
}
I found a function select(), but I don't really understand how it works ...
Is there an alternative with Qt ?
(Sorry for my english)
The Qt mindset is most of the time to work with events, the Qt event loop will do the wait/pause for you. Though select (pselect on linux) does exactly what you want... it is not the Qt way.
A Qt way of doing it could be to connect to both signals of a new frame received and a timeout occured. If your objects are created in your UDP thread, their slots will be executed in the same thread (doc about this).
You can initialize in the run function and create+connect the signals to some custom slot(s), then instead of calling forever you just call exec() (doc). The run function will not return and therefore not terminate your thread, but will be waiting for events until you terminate the thread yourself by calling exit(). You can call it yourself when you have received what you want, or from the main thread to just stop processing the frames at some point.
Then you need a custom slot which process new frames and reset the QTimer to restart the timeout from 0. And eventually another custom slot to handle the timeout, or the same slot depending on what you have to do when it happens.
Now you can see your code is not blocking, so you could probably do all of this directly in the main thread, except if the data processing is long.
Related
I am developing an UI using QTCreator using CPP. My requirement is to run a UI and need to continuously poll linux Message queue using function msgrcv() whether any data is coming to the queue. I created one thread to continuously monitor the reception queue message. While starting and running the mentioned thread, UI got stuck. Any solution for running the thread and UI in parallel?
It's impossible to tell without seeing your code. However, if the poll operation is non-blocking, then you don't actually need a thread. You can instead register a piece of code that Qt's event loop will run on each UI event loop iteration. You do that using a 0ms QTimer:
void poll_function();
// ...
QTimer poll_timer;
QObject::connect(&poll_timer, &QTimer::timeout, poll_function);
poll_timer.start();
Of course, in the above example code, poll_function() will stop getting called once poll_timer goes out of scope. In your real code, you should use a QTimer that stays alive for as long as you need it. Should probably be a data member of your QApplication subclass.
If poll_function() blocks though, then this approach will not work as it will block the UI. So you should make sure to tell msgrcv() to not block. From the man page:
If no message of the requested type is available and IPC_NOWAIT isn't specified in msgflg, the calling process is blocked
So make sure you include IPC_NOWAIT in the msgflg flags when calling msgrcv().
If polling on every UI event loop iteration is too much overhead, then you can instead set a normal timeout interval in milliseconds:
poll_timer.setInterval(500);
This will call your poll function every 500ms.
I have inherited a complex program in my current job and am seeking to reduce image flickering from a stream of data coming over a QTcpSocket.
The program receives the continuous stream of data, processes it, then paints it on the screen with a paintEvent.
The processing function is run based on a signal/slot connection where the signal is readyread() from a QTcpSocket, and the slot is the data processing function. The stream is continuous so this signal/slot is continually firing and updating the painted image on the screen based on the incoming data.
The image flickers constantly, and I assume that the processing in the main event loop could be interfering with the data stream, so my idea was to put the data processing function in its own thread. This data processing function is so thoroughly integrated into the other features of the program, that subclassing the data stream at this point so that I could apply a QThread is not a solution and would be a complete restructure of the entire program, taking tons of time.
So my idea was to use QtConcurrent like so:
void MainWindow::getDataThread(){ //implemented as a slot
wpFuture = QtConcurrent::run(this, &MainWindow::getData);
}
where getData() is the data processing function connected to the readyread() signal:
connect(tcpSocket2, SIGNAL(readyRead()), this, SLOT(getData()));
So I replaced SLOT(getData()) with SLOT(getDataThread()) to allow the data processing function to be run on a new thread that is obtained from the global thread pool. Since the stream is continuous, I believe it is constantly assigning a new thread every time the getData processing function is ran. It does seem to reduce flickering but after about 30 to 60 seconds the program randomly crashes with no specific callouts.
So my question is: Is there a better method for threading my data processing function, without subclassing the data stream? Is my thinking/understanding wrong in my implementation of QtConcurrent in this specific situation?
Thank you.
From your comment I assume your understanding of thread pool is wrong.
There are a number of threads in a thread pool. Each time you call QtConcurrent::run a free thread from the global thread pool is taken and being handed a task to do (MainWindow::getData). If you call QtConcurrent::run several times than every time MainWindow::getData will be executed in (presumably) different thread. If there are no currently available threads in thread pool, you tasks will be queued and handed to threads as they become available later. This way you can have several simultaneous tasks running limited by the number of threads in the thread pool.
Now the problem is, that MainWindow::getData is probably not thread safe by its design. QtConcurrent::run(this, &MainWindow::getData); called several times may result in data race.
If you want a separate single thread to process data then just use QThread (no need to "subclass" anything):
// A thread and its context are created only once
QThread thread;
QObject context;
context.moveToThread(&thread);
// ...
QObject::connect(tcpSocket2, &QTcpSocket::readyRead, &context, [this] () {
this->getData();
}, Qt::QueuedConnection);
thread.start()
Now as long as context object is alive and thread is running each time QTcpSocket::readyRead is emmited - the lambda will be executed.
Still pay attention so that your worker thread and you main thread do not collide in getData.
a few months ago,i had asked some relative questions about qt tcp network programming for my project. And finally the software came out. But after learned more detail about qt event mechans and signals -slots realization. I have some worry about my program performance and stability.
The key problem is that server using a single thread for handle multiple tcpsockets. the brief introduction code for realization:
incomingConnection function is writen as following: two QSignalMapper are used for map each socket SlotReadyRead and SlotDisconnected
void ServerModule::incomingConnection(qintptr socketDescriptor)
{
m_tcpSocket = new QTcpSocket(this);
if (!m_tcpSocket->setSocketDescriptor(socketDescriptor)) {
return;
}
connect(m_tcpSocket, SIGNAL(readyRead()), m_readyReadSignalMapper, SLOT(map()));
m_readyReadSignalMapper->setMapping(m_tcpSocket, m_tcpSocket);
connect(m_tcpSocket, SIGNAL(disconnected()), m_disconnectedSignalMapper, SLOT(map()));
m_disconnectedSignalMapper->setMapping(m_tcpSocket, m_tcpSocket);
}
the sever construct function:
ServerModule::ServerModule(QObject * parent) : QTcpServer(parent),m_readyReadSignalMapper(new QSignalMapper(this)),m_disconnectedSignalMapper(new QSignalMapper(this))
{
connect(m_readyReadSignalMapper, SIGNAL(mapped(QObject *)), this, SLOT(SlotReadyRead(QObject *)));
connect(m_disconnectedSignalMapper, SIGNAL(mapped(QObject *)), this, SLOT(SlotDisconnected(QObject*)));
......other code
}
SlotReadyRead and SlotDisconnected functions are every normal,it convertsQObject* socketObject to QTcpSocket *socket and then do some work.
So i have learned that if write like aboving connect function with specific connect mode
Qt::DirectConnection
Qt::QueuedConnection
Qt::BlockingQueuedConnection
if using single thread,only first mode and second mode can be used . And use first mode, it's synchronous ,if second, it's asynchronous. My program default using first mode, so the signals -slots are connected synchronous.
So here is my worry:
1. How about the single thread performance for handling multiple sockets?can it reach 500 connection /per second concurrency?what's the max connected can be handled?
2. if at the same time,multiple sockets are ready to read then called qt core to send readyRead signals, the QSignalMapper can handle it properly?
3. should I connect socket and QSignalMapper using QueuedConnection mode, because this connecting is not connected immediately, it's using event queue and postEvent to connect. so its asynchronous. Is in this situation,the concurrency request can be handled?
First a few issues with your code:
QSignalMapper just adds complexity to your code
Don't use a member variable for QTcpSocket, you will be overwriting it every time and chances are that you might use an invalid pointer
If you are not doing something complex or using QSslSocket don't subclass QTcpServer, just connect to the newConnection() signal and call nextPendingConnection()
Now to the connect part of your questioning you should read https://woboq.com/blog/how-qt-signals-slots-work.html in short:
Qt::DirectConnection - means once the signal is emitted the slot will called immediately, if the object that has the slot lives in another thread it will be called in the caller thread. This is used if Qt::AutoConnection is used and both objects live in the same thread.
Qt::QueuedConnection - means that when the signal is emitted it will create an event and be put on the event loop to be dispatched once you return to the event loop, this is useful for different threads as the slot will called on the thread that the object lives in. This is NOT what you want here, nor how QTcpSocket should be used (read the docs).
Qt::BlockingQueuedConnection - is very rare to use this one, this like the above puts the event on the event loop of the other thread, but it blocks until the slot was called.
The only "Sync" method is the blocking one, because it would block, but that doesn't mean it's a problem, you can have a non-gui thread that blocks waiting for the reply of the gui thread while asking the user for a password for example.
To the questions now:
UPDATED 1 and 3 for more clarification
Performance really depends on what these sockets will do, how long each will take to process the request and send a reply, in Cutelyst Web Framework a single thread on an i5 can process up to 100K req/s (returning a 'Hello Wolrd!' string HTTP response), the maximum number depends of concurrent connections will be limited by max ports available, memory available to allocate memory and of course if it's CPU intensive the clients will have a long time waiting.
The most common way is to call sender() on your slot, due a small hit on performance (due sender() call) it's faster to use a lambda:
void Parser::readyRead() {
auto socket = qobject_cast<QTcpSocket*>(sender());
...
}
Or with a lambda:
connect(sock, &QTcpSocket::readyRead, [sock] () {
// use sock obj here
});
Again QSignalMapper is not what you want, you should call sender() to get the QTcpSocket or use a lambda capturing the socket object (this is a little faster)
No shouldn't used QueuedConnection connection on your QSignalMapper, because that will cause an unneeded overhead due the fact that it will put the event on the event loop queue and it will be processed later, it might also cause weird bugs due the way QTcpSockets handle data (you must consume all the bytesAvailable() on readyReady since if no extra data arrives readyRead() signal is not emitted again.
I have just started working with QT, and found the nice feature of QTTimer which triggers the slot at the interval of given period. Some point in time, I came across two situations.
1) if the timer is in the pending state, stopping timer have no issues that i won't even move to 'running state'.
2) If the timer is already running ( assume it is a bit long process task), then i found the stop will not terminate/stop 'running state'.
My Question:
At any given point of time, if stop is invoked, i should make sure it is stopped if it is already running.
Example:
connect(&myTimer,SIGNAL(timeout()), this, SLOT(missionStarted()));
When i Stop like this:
myTimer.stop() -> It actually stops the next firing the signal, but it does not stop running state of missionStarted().
What i thought of a solution ?
myTimer.stop();
while (myTimer.isActive()) {
}
qDebug()<<" I am guaranteed that missionStarted() is no more running, will not run anymore" ;
Is the solution is a way to go?. please guide me.
Does Qt Timer API stop and terminate the running slot?
No. The timer stop does not terminate running slot.
And how can I make it wait to get the timer slot execution completed?
There several ways to do so: with the signal back to the object that has the timer, for instance:
void MyWorkerClass::mySlot()
{
doTheJob();
emit signalIamDone();
}
And the the object that has the timer can acknowledge the slot stopped by connecting to that signalIamDone:
connect(&workerObj, SIGNAL(signalIamDone()), &managerObj, SLOT(workerJobDoneSlot()));
The actual slot:
void MyManagerClass::workerJobDoneSlot()
{
doSomethingOnJobFinished();
}
I would also try to use condition variable wait if you had a manager and worker thread but it seems like everything is running on one main UI thread.
And mind that usually the worker slot is getting called on the same main thread as your manager object runs unless your manager object is specifically running in the context of own thread. So, unless told otherwise about threads, you always have it waiting on the slot finishing you just need to know that the wait is over or doSomethingOnJobFinished called.
I asked this question yesterday since I wasn't receiving any data but strangely when I used wait in the destructor I started receveing notification from QSocketNotifier. The rest of the question is same. Can someone suggest something?
I have created a sample application from where separate thread is started to read and process data from serial port. QSocketNotifier is used for detecting whether data has arrived on the serial ports or not. I start an event loop using exec() statement in run function of thread. But while running the application only once the socket notifier has worked, the signal for serial port activation is never generated. And once when it was generated it was generated very fast and wasn't equivalent to the frame rate of sending device.
Here is a brief code sample for serial communicator thread:
SerialPortWatchOne.cpp
//constructor
klass::klass()
{
//setport configuration
//miscellaneous initialization
QSocketNotifier* notifier = new QSocketNotifier(mPort->GetFileDescriptor, QSocketNotifier::Read,this);
connect(notifier,SIGNAL(activated(int)),this,SLOT(ReadAndProcessData()));
}
void klass::run()
{
exec(); //this starts an event loop where by Qt signal handling is enabled
}
void klass::ReadAndProcessData()
{
FlushBuf();
int bytes_read=mPort->ReadPort(mBuf,1000);
if(bytes_read>0)
//Process data
}
~klass::klass()
{
//desctruction code;
wait(); //so that thread cleanly releases all resources before exit
}
Note: klass is a thread and a member of GUI thread and is instantiated in the GUI thread c'tor. periodically GUI updates its widgets with data from klass thread.
Can anyone suggest as what the issue is? Has someone done this before.
Only thing that comes to mind is that you're using QSocketNotifier * socketNotifier without an event loop running in the socketNotifier->thread() thread. If no event loop is running, you'll get no event handling. No event handling means no signals fired from QSocketNotifier. But if you're using a separate thread, you might want to use blocking I/O calls anyway.