QSocketNotifier warning -- using socket inside a thread - qt

I am able to remove this warning, please suggest on below points.
QSocketNotifier: socket notifiers cannot be enabled from another thread
Whenever new request comes to QTcpServer i create new object -- xxx . This object then create thread for this socket & send receive data in
dowork_socket() function of yyy object. Inside dowork_socket() function i emit signal signalTcpSocketWriteData() to send data from socket.
Object creating the thread for new socket - xxx (I am not pasting full code):----
yyy * ptr;
QTcpSocket *m_pTcpSocket;
public slots:
void writeDataSlot( QByteArray data )
{
m_pTcpSocket->write( data );
m_pTcpSocket->flush();
}
Object in which thread is moved -- yyy (I am not pasting full code) :----
xxx *TcpSocketWrapper_ptr;
signals:
void signalTcpSocketWriteData( QByteArray);
public slots:
void dowork_socket();
Inside above object yyy contructor I am connecting signal signalTcpSocketWriteData to slot writeDataSlot :---
connect(this, SIGNAL(signalTcpSocketWriteData( QByteArray)), TcpSocketWrapper_ptr, SLOT(writeDataSlot( QByteArray )), Qt::QueuedConnection );
dowork function of object yyy :--
void TcpSocketThreadObject::dowork_socket()
{
QByteArray block;
block.append(" \n hi again .. !!!");
emit signalTcpSocketWriteData(block);
}
I am able to send data success fully by above method & above warning is removed.
1> Now my question is suppose two threads are created & both thread simultaneously emit the signal then will there be conflict in running the slot ?
2> Will it cause some critical section problem or events are queued & will not be executed simultaneously ?
Please suggest on this two points.

that seems too complicated. You don't need to create threads to work with sockets.
Whatever, if you do this, here's two points needs to be kept in mind:
QTcpSocket is Not thread-safe itself
as long as you use Qt::QueuedConnection when connecting slot (or at least proper using of implicit connections between different threads do this) all code executing inside connected slot will be execited in object's thread loop. In other words, signals emitted from different thread(s) will be queued.

Related

QT how to restart a thread?

How to properly restart a QThread? I have been googling this four hours and can't find any concrete answer.
What I have is the basic moveToThread implementation:
VideoHandler::VideoHandler()
{
VideoBurner *videoBurner = new VideoBurner;
videoBurner->moveToThread(&videoBurnerThread);
connect(this, &VideoHandler::signalVideoData, videoBurner, &VideoBurner::setVideoData);
connect(this, &VideoHandler::signalVideoBurn, videoBurner, &VideoBurner::initVideoBurn);
// don't really want it since there is only 1 object
//connect(&videoBurnerThread, &QThread::finished, videoBurner, &QObject::deleteLater);
connect(videoBurner, &VideoBurner::burnProcess, this, [=](QString step, int percentage){
emit burningProcess(step, percentage);
});
}
This is the declaration of my Class:
class VideoHandler : public QObject
{
Q_OBJECT
QThread videoBurnerThread;
...
bunch of defintions
...
}
The VideoBurner class is also a subclass of QObject
class VideoBurner : public QObject
{
Q_OBJECT
...
bunch of definitions
...
}
For the first run this works perfect, signals and slots all work.
The issue happens when I want to "cancel" the thread.
For example it is working on some "heavy" calculation that I want to stop from the main thread so I call: videoBurnerThread.quit(); with a cancel function from VideoHandler.
I don't wait() on it as it would block the main thread.
quit() triggers &QThread::finished, but I commented out that connection as it destroys my only object instance.
(also I can't find any example that creates an object and puts it on a thread outside a constructor, if that's even possible? when I tried the app would just close without errors)
I found that the quit() only stops the event loop, not doing anything besides that, which leads to the issue of restarting the tread.
After I want to do the "heavy" stuff again, and I call videoBurnerThread.start(); to start it again, I get results of last performed function from VideoBurner and some signals from it, before it actually starts doing what it should.
Can I somehow stop whatever it was working on and just restart it? I tried sending an "abort" signal from VideoHandler so it doesn't emit signals, but that didn't work.
Do I absolutely need the &QObject::deleteLater so it stops? If so, how to reinitialize VideoBurner correctly inside some function and reconnect it's signal/slot?
Also there is no logic in VideoBurner destructor just a public: virtual ~VideoBurner(){};, could this be an issue?
Call "this->deleteLater()" at the end of your worker.
Connect the worker destroyed signal to the thread quit slot in your Handler function.
Refer to this code snippet.
if(!dataThread.isRunning())
{
worker = new Worker();
dataThread.setObjectName("dataThread");
worker->moveToThread(&dataThread);
QObject::connect(&dataThread, &QThread::started, worker, &Worker::run);
QObject::connect(worker, &Worker::destroyed, &dataThread, &QThread::quit);
QObject::connect(worker, &Worker::set_counter_label, this, &MainWindow::update_counter);
dataThread.start();
}

Qt how doing a blocking wait until receiving data

I have a qt program. I have CAN requests that I want to send in sequential order.
I want to wait for answers, before sending other requests.
SendReadLatchCommand(fam,prod,addr,0x00000000, 4); // 1st request
// wait for answer and analyze it??
SendReadLatchCommand(fam,prod,addr,0x00000002, 4); // 2nd request
I have a receiveData() method, called by my thread of reception, where I save the received message.
I want to sleep in my main program and we awake when receiving answer.
I can't use signal/slot because in the slot, I don't know what is the last request I sent, so I can't continue emitting requests.
How can I do this?
thanks
If i understand you properly, you wanted to process the request synchronously.
Look into the QEventLoop in the qtdoc, you can do it this way:
QEventLoop wait_loop;
// 1st request
connect(request_1, SIGNAL(sig_answer_arrived()), &wait_loop, SLOT(quit()));
request_1->send_request();
wait_loop.exec();
// here we already got the answer
analyze_answer();
// the 2nd request does the same
I'm not sure whether it is a good idea to block your main thread, however it can be done by using a binary semaphore, which is the same as a counting semaphore with a maxCount of 1. Therefore one can use a counting semaphore QSemaphore
Typically, a QSemaphore is implemented in terms of QWaitCondition (refer Qt help). One could block on a wait condition until the CAN thread signals the wait condition. One can hide the blocking on the wait behind some interface e.g:
//--- Very simple implementation - concept only
QWaitCondition cond_;
QMutex mutex_;
void rxThreadHandler( /*args*/ )
{
while( !quitCalled() )
{
waitOnReceivedData();//Blocks, I assume...
handleReceivedData();
answerRxd();
}
}
void answerRxd()
{
QMutexLocker lock( mutex_ );
cond_.wakeAll();
}
void sendNext( const Buffer& buffer )
{
QMutexLocker guard( mutex_ );
//Waits/Blocks until condition signalled, then locks mutex
// to prevent further signalling (might block rx thread)
cond_.wait( lock.mutex() );
//Unlocking mutex explicitly to allow receipt of data
guard.unlock();
//Now send as result of previous receive. This does not
// prevent receiving thread...
sendNextImpl( const Buffer& buffer );
}

Qt Signals and slots mechanism blocked by a loop in main

I have a following situatuion.
2 Socket objects are created in the main in a for loop (the original problem has 1000 objects). Upon creation the start() method is invoked.
start() creates a QTcpSocket which tries to connect to some host.
Socket has slots which catch the connected() signal from QTcpSocket and print some debug output
What happens is that chronologically first ALL the Socket objects are created after which the sockets are started. Here is an example output of debug options:
1. Created Socket object 1
2. Invoked Socket object 1 start()
3. Created Socket object 2
4. Invoked Socket object 2 start()
5. Socket object 1 TcpSocket Connected
6. Socket object 2 TcpSocket Connected
Code:
//main.cpp
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
for (int i=0; i<10; i++)
{
Socket *socket = new Socket();
qDebug() << "Socket object created";
socket->Start();
}
return a.exec();
}
//socket.cpp
Socket::Socket(QObject *parent)
: QObject(parent)
{}
void Socket::Start()
{
qDebug()<<"Start method invoked";
socket = new QTcpSocket(this);
connect(socket,SIGNAL(connected()), this, SLOT(on_connect()), Qt::DirectConnection);
socket->connectToHost("192.168.5.5",12345);
}
void Socket::on_connect()
{
QTcpSocket* socket = qobject_cast<QTcpSocket *>(QObject::sender());
qDebug() << socket->socketDescriptor() << " Connected.";
}
This is not the behavior I expected because the documentation states:
When a signal is emitted, the slots connected to it are usually
executed immediately, just like a normal function call. When this
happens, the signals and slots mechanism is totally independent of any
GUI event loop.
Question:
How to ensure the slots are executed "immediately" (not only after the loop in the main finishes) when the signal is emitted?
The only available solution (without introducing new threads) i currently see:
Drop the use of signals and slots in this case, and implement everything in the start method. Something like this:
Socket::start(){
...
if(!tcpsocket->waitForConnected(200)) qDebug() << "Socket object X TcpSocket Connected"
...
}
Your slot is indeed triggered immediately when QTcpSocket's signal connected() is emitted.
However, connected() is not emitted the moment you try to connect that socket to somewhere.
The documentation writes:
This signal is emitted after connectToHost() has been called
and a connection has been successfully established.
The establish of a connection requires an event loop.
establishing the connection happens asynchronously (read connectToHost will return immediately before it even checks whether the connection has already been established) and will notify your code using the signals that are triggered by events
these events are handled only in the event loop or when you call WaitForConnect (which will spin up it's own even loop only handling those events)
this means that the sequence you get is perfectly normal
I don't think you can do that without introducing new threads, only solution is seems your solution.
Or using DirectConnection instead of leaving it empty (Which is AutomaticConnection and which is QueuedConnection in your case) may be a solution. But I don't think that it will work because you need to wait in order to run that slot. I'm not sure, just give it a try.

How to implement "first come first served" scheduling algorithm using threading in Qt C++ programming?

I wish to add processes to a dynamic list then schedule those processes using the "first come first served" scheduling algorithm. The scheduling algorithm should only run a max of 5 processes concurrently and when a process has been terminated it should it should emit a signal to indicate termination.
Then when a process has been terminated, another process should be scheduled by the scheduling algorithm once there are processes in the queue.
Note also that each process has access to a shared list of integer which only one process can access at a time. I already know how to do this part by locking the shared integer list using QMutex. Ideally, I am seeking an example, so I can understand it.
//mutex example
QMutex mutex
while(!mutex->tryLock()){
//enter code here
}
this->performTask(); //
mutex.unlock();
You will have 5 instances of a class that extends QThread. Each class will execute a QProcess and wait for it to finish.
class MyThread : public QThread
{
public:
MyThread(MyScheduler& aScheduler)
: iScheduler(aScheduler)
{
}
void ExecuteProgram(const QString& aProgramName)
{
iProgramName = aProgramName;
start();
}
void run()
{
iProcess.start(iProgramName);
iProcess.waitForFinished(-1);
iScheduler.SignalProgramTerminated(this);
}
private:
MyScheduler& iScheduler; // This is your FCFS scheduler.
QString iProgramName;
QProcess iProcess;
};
(I haven't compiled this but it should give you some headway).
You could use QThreadPool to create a pool of 5 threads that run your processes and use QQueue to queue the pending processes in a FIFO fashion.
edit:
About mutexes:
The mutex protects a piece of code form beeing executed by more than one thread. A thread tying to lock a mutex will be blocked until no other thread holds the lock. The easiest way to use mutexes is with the QMutexLocker.
void myclass::modifyList(IntegerList* list)
{
QMutexLocker lock(list->getMutex()); //this will block if an other thread holds the mutes
//do stuff
}

Implementing a TCP Server

Can anyone tell me if I'm doing this right?
Using Qt I'm implementing a TCP Server by inheriting from the QTcpServer class. On an incoming connection I create a new thread, a new Worker object, and I move the object to the new thread and start the thread. From here, the server keeps listening for new clients and each thread then is in its run method for object Worker.
Now, I create a timer because I need to send updates to each client based on 1 second intervals AND when a song is playing. In the readyRead slot I read data using readAll and then perform some work and send a reply.
However, when I go back to my run method I need to just continue sending song data updates to the clients (with no response from the client). Should this all just go in a while(true) loop and then I check some boolean to start and stop the timer? The track information I need to send is the song progression time.
I guess my question is, should I be doing it this way? It seems a little complex, but then again that's concurrency for you. Basically I need the TCP server to send data to the client repeatedly when some condition is true. I feel like just an endless while loop that checks when to start and stop the timer is useless work.
Would posting code make this clearer?
This question is a very old one, but perhaps it could still help.
About threads in Qt:
Many people think about parallel processing in Qt like in .NET where you need for every operation another thread, in qt this is not necessary!
In qt you only need a thread if you have blocking code like calculating big things or waiting syncron for an answer from a SQLServer
If i have understand you correctly you don't have such a blocking operation.
So i have programmed a very small TcpServer without inheriting and without a single thread (except the main eventloop thread of course), which hopefully solves your problem and help others:
#include <QObject>
#include <QSet>
#include <QTcpServer>
#include <QTcpSocket>
#include <QTimer>
class TcpServer : public QObject
{
Q_OBJECT
public:
TcpServer()
{
// handle new connections
this->connect(&this->serverTcp, &QTcpServer::newConnection, this, &TcpServer::handleClientConnect);
// init client refresh timer
this->timer.setInterval(1000);
this->connect(&this->timer, &QTimer::timeout, this, &TcpServer::handleClientUpdates);
this->timer.start();
}
bool startListen(qint16 port)
{
return this->serverTcp.listen(QHostAddress::Any, port);
}
private slots:
void handleClientConnect()
{
QTcpSocket* socketClient = *this->setConnectedClients.insert(this->serverTcp.nextPendingConnection());
this->connect(socketClient, &QTcpSocket::disconnected, this, &TcpServer::handleClientDisconnect);
this->connect(socketClient, &QTcpSocket::readyRead, this, &TcpServer::handleClientData);
}
void handleClientDisconnect()
{
this->setConnectedClients.remove((QTcpSocket*)this->sender());
}
void handleClientData()
{
QTcpSocket* socketSender = (QTcpSocket*)this->sender();
// handle here the data sent by the client
}
void handleClientUpdates()
{
// construct here your update data
QByteArray baUpdateResponse = "test";
// send update data to all connected clients
foreach(QTcpSocket* socketClient, this->setConnectedClients) {
socketClient->write(baUpdateResponse);
}
}
private:
QTcpServer serverTcp;
QTimer timer;
QSet<QTcpSocket*> setConnectedClients;
};

Resources