Multithreaded application - multithreading

I have an application which runs 2 worker threads separate from the main GUI thread.
Thread 1:
needs to send some data to thread 2 every 100 ms.
sleeps for 10ms in each loop of its run.
Header:
class thread1:public QThread
{
Q_OBJECT
public:
thread1();
~thread1();
signals:
void wakeThread2();
void sendValue(int);
void sleepThread2();
protected:
void run();
private:
volatile bool stop;
int data;
};
Implementation:
thread1::thread1():stop(false),data(0)
{
}
void thread1::run()
{
while(!stop)
{
++data;
if(data==1000)
data = 0;
cout<<"IN THREAD 1 with data = "<<data<<endl;
emit sendValue(data);
emit wakeThread2();
emit sleepThread2();
msleep(10);
}
}
Thread 2
Header:
class thread2:public QThread
{
Q_OBJECT
public:
thread2();
~thread2();
private slots:
void receiveValue(int);
void Sleep();
protected:
void run();
private:
volatile bool stop;
int data;
};
Implementation:
thread2::thread2():stop(false),data(0)
{
}
void thread2::run()
{
if(!stop)
cout<<"IN THREAD..............2 with data = "<<data<<endl;
}
void thread2::receiveValue(int x)
{
data = x;
}
void thread2::Sleep()
{
msleep(100);
}
MainWindow:
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
t1 = new thread1;
t2 = new thread2;
QObject::connect(t1,SIGNAL(wakeThread2()),t2,SLOT(start()));
QObject::connect(t1,SIGNAL(sendValue(int)),t2,SLOT(receiveValue(int)));
QObject::connect(t1,SIGNAL(sleepThread2()),t2,SLOT(Sleep()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_startT1_clicked()
{
t1->start();
}
Output:
IN THREAD 1 with data = 1
IN THREAD..............2 with data = 1
IN THREAD 1 with data = 2
IN THREAD 1 with data = 3
IN THREAD 1 with data = 4
IN THREAD 1 with data = 5
IN THREAD 1 with data = 6
IN THREAD 1 with data = 7
IN THREAD 1 with data = 8
IN THREAD 1 with data = 9
IN THREAD 1 with data = 10
IN THREAD 1 with data = 11
IN THREAD..............2 with data = 2
IN THREAD 1 with data = 12
IN THREAD 1 with data = 13
IN THREAD 1 with data = 14
IN THREAD 1 with data = 15
IN THREAD 1 with data = 16
IN THREAD 1 with data = 17
IN THREAD 1 with data = 18
IN THREAD 1 with data = 19
IN THREAD 1 with data = 20
The data in thread 2 is not getting updated with the latest value of thread 1 and the GUI window is totally frozen. Please let me know if there is better/more efficient way to implement multi thread applications with Qt and to communicate between threads.
EDIT : ACCORDING TO LUCA the Thread1 remains almost the same...while Thread2.h looks like this
Thread2.h
#include <QThread>
#include <QTimer>
#include "iostream"
using namespace std;
class Thread2 : public QThread
{
Q_OBJECT
public:
Thread2();
~Thread2();
void startThread();
public slots:
void receiveData(int);
protected:
void run();
private:
volatile bool stop;
int data;
QTimer *timer;
};
and Implementation is....Thread2.cpp..
#include "thread2.h"
Thread2::Thread2():stop(false),data(0)
{
timer = new QTimer;
QObject::connect(timer,SIGNAL(timeout()),this,SLOT(start()));
}
Thread2::~Thread2()
{
delete timer;
}
void Thread2::receiveData(int x)
{
this->data = x;
}
void Thread2::run()
{
cout<<"thread 2 .........data = "<<data<<endl;
}
void Thread2::startThread()
{
timer->start(100);
}
and the mainwindow.cpp looks like this...
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent),
ui(new Ui::MainWindow)
{
ui->setupUi(this);
t1 = new Thread1;
t2 = new Thread2;
QObject::connect(t1,SIGNAL(sendData(int)),t2,SLOT(receiveData(int)));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_pushButton_start_thread1_clicked()
{
t1->start();
t2->startThread();
}

It seems to me data is actually updated. But thread 1 is 10 times faster than thread 2. When you emit the Sleep signal, thread 2 is put to sleep for 100ms, which makes it unable to process other signals. Those will be placed in a queue and processed as soon as the control returns to the event loop. Then you'll see the message with data updated.
The specification anyway is quite weird for me: I read "thread 1 needs to send data to thread 2 every 100 ms....", but I see you do it every 10ms, but then you say "thread 1 itself sleeps for 10ms in each loop of its run". What is thread 1 supposed to do for the rest of the time?
EDIT: I don't think this is exactly what you wanted, but still I'm not completely sure I understand what you're looking for. Not a complete or good implementation, just to give the idea:
#include <QCoreApplication>
#include <QTimer>
#include <QThread>
class Thread1 : public QThread
{
Q_OBJECT
public:
explicit Thread1() :
data(0) {
// Do nothing.
}
void run() {
while (true) {
data++;
qDebug("Done some calculation here. Data is now %d.", data);
emit dataChanged(data);
usleep(10000);
}
}
signals:
void dataChanged(int data);
private:
int data;
};
class Thread2 : public QObject
{
Q_OBJECT
public:
explicit Thread2() {
timer = new QTimer;
connect(timer, SIGNAL(timeout()), this, SLOT(processData()));
timer->start(100);
}
~Thread2() {
delete timer;
}
public slots:
void dataChanged(int data) {
this->data = data;
}
void processData() {
qDebug("Processing data = %d.", data);
}
private:
QTimer* timer;
int data;
};
int main(int argc, char *argv[])
{
QCoreApplication a(argc, argv);
Thread1 t1;
Thread2 t2;
qApp->connect(&t1, SIGNAL(dataChanged(int)), &t2, SLOT(dataChanged(int)));
t1.start();
return a.exec();
}
#include "main.moc"
The output is:
Done some calculation here. Data is now 1.
Done some calculation here. Data is now 2.
Done some calculation here. Data is now 3.
Done some calculation here. Data is now 4.
Done some calculation here. Data is now 5.
Done some calculation here. Data is now 6.
Done some calculation here. Data is now 7.
Done some calculation here. Data is now 8.
Done some calculation here. Data is now 9.
Done some calculation here. Data is now 10.
Processing data = 10.
Done some calculation here. Data is now 11.
Done some calculation here. Data is now 12.
Done some calculation here. Data is now 13.
Done some calculation here. Data is now 14.
Done some calculation here. Data is now 15.
Done some calculation here. Data is now 16.
Done some calculation here. Data is now 17.
Done some calculation here. Data is now 18.
Done some calculation here. Data is now 19.
Processing data = 19.
Done some calculation here. Data is now 20.
Done some calculation here. Data is now 21.
Done some calculation here. Data is now 22.
Done some calculation here. Data is now 23.
Done some calculation here. Data is now 24.
Done some calculation here. Data is now 25.
Done some calculation here. Data is now 26.
Done some calculation here. Data is now 27.
Done some calculation here. Data is now 28.
Processing data = 28.
...
Beware that Thread2 actually is the main thread (i.e. UI thread) of your application. Move the object to a different thread if you need it.

Related

how to pass structure to QT thread

Am trying to pass data structure to QT thread and but no success.
here is what am doing and have done.
i prepare data for the thread, like this and then tried to pass prepared data to thread before starting.
void mytable::prepare_data(){
// get table row count
int rowCount = ui->my_table_view->rowCount();
// create structure array based on rowCount
pnp_com_info pnp_data[rowCount];
/* pnp_com_info structure defined it top of file below includes to make it global
struct pnp_com_info{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
*/
// loop on table rows columns and load pnp_data with data of columns
// PROBLEM : how to pass pnp_data structure to thread side ?
// can pass basic vars like
RunJobThread->mynum = 10;
// start QT thread
RunJobThread->start();
// std:: thread experiment
// std::stdthreadtest(pnp_data,rowCount);
}
run_job_thread.h source code
#ifndef RUN_JOB_THREAD_H
#define RUN_JOB_THREAD_H
#include <QObject>
#include <QThread>
class run_job_thread : public QThread
{
Q_OBJECT
public:
run_job_thread();
void run();
int mynum;
struct pnp_com_info_thread{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
bool Stop; // bool to stop the job
signals:
void select_row_of_table_signal(int);
public slots:
};
#endif // RUN_JOB_THREAD_H
run_job_thread.cpp source code
#include "run_job_thread.h"
#include <QtCore>
run_job_thread::run_job_thread()
{
}
// run the thread
void run_job_thread::run(){
qDebug() << "my num passed value is : "<<this->mynum; // output : 10
// Goal : loop on pnp_data structure and emit signal to table rows
emit select_row_of_table_signal(5);
}
things i tried
instead of struct i tried to use other data containers like map, multimap, vectors but they give error , as am initializing pnp_com_info struct inside mytable::prepare_data() function based on rowCount which make it local and limited to prepare_data() function but with map,multimap,vector my plan was that they will be global and i will be able to access it from thread, however it not worked.
std::map<std::string, int,int,int> pnp_com_info; // error: too many template arguments for class template 'map'
std::multimap<std::string, int,int,int,bool> pnp_com_info; // error: too many template arguments for class template 'multimap'
std::vector<std::string, int,int,int,bool> pnp_com_info; // error: too many template arguments for class template 'vector'
i also tried std::thread which was partial success , i mean it was working ok but looks like std::thread not works with QT GUI thread as upon running app GUI will go freez although std::thread was doing its job
I would suggest to do the following, because the declaration of the
pnp_com_info pnp_data[rowCount];
is inside a context i think their lifecycle will be lost once you leave it, other problem is that it would be really "unsafe" to create this kind of arrays and then pass it from one side to another. Therefore I would create a QList and then pass either a copy or the reference to the worker thread. So
1) Create a QList pnp_data, in the public part of mytable
2) Fill all data using a for loop as follows.
3) Create another QList pnp_data or a QList *pnp_data (if you want to use a copy or a pointer)
4) Then just pass either a copy or a reference to the worker thread.
Then it should look like this:
mytable.h source code
public: QList<pnp_com_info> pnp_data;
mytable.cpp source code
void mytable::prepare_data(){
// get table row count
int rowCount = ui->my_table_view->rowCount();
// HERE YOU LOAD ALL THE VALUES TO THE LIST
for(int i = 0; i<rowCount; i++){
pnp_com_info itemToInsert;
//FILL HERE THE itemToInsert
//Insert the item inside the list.
pnp_data.append(itemToInsert);
}
// PROBLEM : how to pass pnp_data structure to thread side ?
// Either pass it as a copy
RunJobThread->pnp_data = pnp_data;
//or as a reference
QList<pnp_com_info> *pnpDataPointer = &pnp_data;
RunJobThread->pnp_data_reference = pnpDataPointer;
// start QT thread
RunJobThread->start();
// std:: thread experiment
// std::stdthreadtest(pnp_data,rowCount);
}
run_job_thread.h source code
#ifndef RUN_JOB_THREAD_H
#define RUN_JOB_THREAD_H
#include <QObject>
#include <QThread>
class run_job_thread : public QThread
{
Q_OBJECT
public:
run_job_thread();
void run();
struct pnp_com_info_thread{
QString com_name = "";
int x = 0;
int y = 0;
int angle = 0;
bool status = false;
};
QList<pnp_com_info> pnp_data; //This one if you create a copy
QList<pnp_com_info> *pnp_data_reference; //This if you want a pointer
bool Stop; // bool to stop the job
signals:
void select_row_of_table_signal(int);
public slots:
};
#endif // RUN_JOB_THREAD_H
I hope this helps.
First, don't subclass QThread to create a worker - re-read How To Really, Truly Use QThreads; The Full Explanation by Maya Posch. You will find it much more manageable to create a worker object and connect the threads started() to your worker's main method, and the worker's signals to the thread's quit() and deleteLater().
Then, it should be much more straightforward to pass your data to the worker before it's moved to the thread, or to use a signal connection if it needs to be passed when the worker is running (remember to register your structure with the meta-object system for that).

cannot handle QNetworkAccessManager::finised signal in multithreading

I want to serialize network requests using QNetworkAccessManager. For achieving it i wrote such class:
#ifndef CLIENT_H
#define CLIENT_H
#include <queue>
#include <mutex>
#include <condition_variable>
#include <QtNetwork/QNetworkAccessManager>
#include <QtNetwork/QNetworkReply>
#include <QtNetwork/QNetworkRequest>
class Client : public QObject
{
Q_OBJECT
struct RequestRecord
{
RequestRecord(QString u, int o):url(u),operation(o){}
QString url;
int operation;
};
std::mutex mutex;
std::queue<RequestRecord*> requests;
QNetworkAccessManager *manager;
bool running;
std::condition_variable cv;
public:
Client():manager(nullptr){}
~Client()
{
if(manager)
delete manager;
}
void request_cppreference()
{
std::unique_lock<std::mutex> lock(mutex);
requests.push(new RequestRecord("http://en.cppreference.com",0));
cv.notify_one();
}
void request_qt()
{
std::unique_lock<std::mutex> lock(mutex);
requests.push(new RequestRecord("http://doc.qt.io/qt-5/qnetworkaccessmanager.html",1));
cv.notify_one();
}
void process()
{
manager = new QNetworkAccessManager;
connect(manager,&QNetworkAccessManager::finished,[this](QNetworkReply *reply)
{
std::unique_lock<std::mutex> lock(mutex);
RequestRecord *front = requests.front();
requests.pop();
delete front;
reply->deleteLater();
});
running = true;
while (running)
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock);
RequestRecord *front = requests.front();
manager->get(QNetworkRequest(QUrl(front->url)));
}
}
};
#endif // CLIENT_H
As one can see, there are 2 methods for requesting data from network and method process, which should be called in separate thread.
I'm using this class as follows:
Client *client = new Client;
std::thread thr([client](){
client->process();
});
std::this_thread::sleep_for(std::chrono::seconds(1));
client->request_qt();
std::this_thread::sleep_for(std::chrono::milliseconds(1));
client->request_cppreference();
This example illustrate 2 consecutive requests to network from one thread and processing of these request in another. All works fine except my lambda is never called. Requests are sent (checked it using wireshark), but i cannot get replies. What is the cause?
as #thuga suppose the problem was in event loop. My thread always waiting on cv and thus cannot process events, little hack solve the problem:
void process()
{
manager = new QNetworkAccessManager;
connect(manager,&QNetworkAccessManager::finished,[this](QNetworkReply *reply)
{
std::unique_lock<std::mutex> lock(mutex);
RequestRecord *front = requests.front();
requests.pop();
delete front;
qDebug() << reply->readAll();
processed = true;
reply->deleteLater();
});
running = true;
while (running)
{
{
std::unique_lock<std::mutex> lock(mutex);
cv.wait(lock);
if(requests.size() > 0 && processed)
{
RequestRecord *front = requests.front();
manager->get(QNetworkRequest(QUrl(front->url)));
processed = false;
QtConcurrent::run([this]()
{
while (running)
{
cv.notify_one();
msleep(10);
}
});
}
}
QCoreApplication::processEvents();
}
}
};
it's not beautiful obvious since it is using 3 threads instead of 2, but it is Qt with this perfect phrase:
QUrl QNetworkReply::url() const Returns the URL of the content
downloaded or uploaded. Note that the URL may be different from that
of the original request. If the
QNetworkRequest::FollowRedirectsAttribute was set in the request, then
this function returns the current url that the network API is
accessing, i.e the url emitted in the QNetworkReply::redirected
signal.

How many mutex(es) should be used in one thread

I am working on a c++ (11) project and on the main thread, I need to check the value of two variables. The value of the two variables will be set by other threads through two different callbacks. I am using two condition variables to notify changes of those two variables. Because in c++, locks are needed for condition variables, I am not sure if I should use the same mutex for the two condition variables or I should use two mutex's to minimize exclusive execution. Somehow, I feel one mutex should be sufficient because on one thread(the main thread in this case) the code will be executed sequentially anyway. The code on the main thread that checks (wait for) the value of the two variables wont be interleaved anyway. Let me know if you need me to write code to illustrate the problem. I can prepare that. Thanks.
Update, add code:
#include <mutex>
class SomeEventObserver {
public:
virtual void handleEventA() = 0;
virtual void handleEventB() = 0;
};
class Client : public SomeEventObserver {
public:
Client() {
m_shouldQuit = false;
m_hasEventAHappened = false;
m_hasEventBHappened = false;
}
// will be callbed by some other thread (for exampe, thread 10)
virtual void handleEventA() override {
{
std::lock_guard<std::mutex> lock(m_mutexForA);
m_hasEventAHappened = true;
}
m_condVarEventForA.notify_all();
}
// will be called by some other thread (for exampe, thread 11)
virtual void handleEventB() override {
{
std::lock_guard<std::mutex> lock(m_mutexForB);
m_hasEventBHappened = true;
}
m_condVarEventForB.notify_all();
}
// here waitForA and waitForB are in the main thread, they are executed sequentially
// so I am wondering if I can use just one mutex to simplify the code
void run() {
waitForA();
waitForB();
}
void doShutDown() {
m_shouldQuit = true;
}
private:
void waitForA() {
std::unique_lock<std::mutex> lock(m_mutexForA);
m_condVarEventForA.wait(lock, [this]{ return m_hasEventAHappened; });
}
void waitForB() {
std::unique_lock<std::mutex> lock(m_mutexForB);
m_condVarEventForB.wait(lock, [this]{ return m_hasEventBHappened; });
}
// I am wondering if I can use just one mutex
std::condition_variable m_condVarEventForA;
std::condition_variable m_condVarEventForB;
std::mutex m_mutexForA;
std::mutex m_mutexForB;
bool m_hasEventAHappened;
bool m_hasEventBHappened;
};
int main(int argc, char* argv[]) {
Client client;
client.run();
}

properly ending an infinite std::thread

I have a reusable class that starts up an infinite thread. this thread can only be killed by calling a stop function that sets a kill switch variable. When looking around, there is quite a bit of argument over volatile vs atomic variables.
The following is my code:
program.cpp
int main()
{
ThreadClass threadClass;
threadClass.Start();
Sleep(1000);
threadClass.Stop();
Sleep(50);
threaClass.Stop();
}
ThreadClass.h
#pragma once
#include <atomic>
#include <thread>
class::ThreadClass
{
public:
ThreadClass(void);
~ThreadClass(void);
void Start();
void Stop();
private:
void myThread();
std::atomic<bool> runThread;
std::thread theThread;
};
ThreadClass.cpp
#include "ThreadClass.h"
ThreadClass::ThreadClass(void)
{
runThread = false;
}
ThreadClass::~ThreadClass(void)
{
}
void ThreadClass::Start()
{
runThread = true;
the_thread = std::thread(&mythread, this);
}
void ThreadClass::Stop()
{
if(runThread)
{
runThread = false;
if (the_thread.joinable())
{
the_thread.join();
}
}
}
void ThreadClass::mythread()
{
while(runThread)
{
//dostuff
Sleep(100); //or chrono
}
}
The code that i am representing here mirrors an issue that our legacy code had in place. We call the stop function 2 times, which will try to join the thread 2 times. This results in an invalid handle exception. I have coded the Stop() function in order to work around that issue, but my question is why would the the join fail the second time if the thread has completed and joined? Is there a better way programmatically to assume that the thread is valid before trying to join?

Why this boost thread creation does't compile?

I wrote some multithreading code using Boost thread library. I initialized two threads in the constructor using the placeholder _1 as the argument required by member function fillSample(int num). But this doesn't compile in my Visual Studio 2010. Following is the code:
#include<boost/thread.hpp>
#include<boost/thread/condition.hpp>
#include<boost/bind/placeholders.hpp>
#define SAMPLING_FREQ 250
#define MAX_NUM_SAMPLES 5*60*SAMPLING_FREQ
#define BUFFER_SIZE 8
class ECG
{
private:
int sample[BUFFER_SIZE];
int sampleIdx;
int readIdx, writeIdx;
boost::thread m_ThreadWrite;
boost::thread m_ThreadRead;
boost::mutex m_Mutex;
boost::condition bufferNotFull, bufferNotEmpty;
public:
ECG();
void fillSample(int num); //get sample from the data stream
void processSample(); //process ECG sample, return the last processed
};
ECG::ECG() : readyFlag(false), sampleIdx(0), readIdx(0), writeIdx(0)
{
m_ThreadWrite=boost::thread((boost::bind(&ECG::fillSample, this, _1)));
m_ThreadRead=boost::thread((boost::bind(&ECG::processSample, this)));
}
void ECG::fillSample(int num)
{
boost::mutex::scoped_lock lock(m_Mutex);
while( (writeIdx-readIdx)%BUFFER_SIZE == BUFFER_SIZE-1 )
{
bufferNotFull.wait(lock);
}
sample[writeIdx] = num;
writeIdx = (writeIdx+1) % BUFFER_SIZE;
bufferNotEmpty.notify_one();
}
void ECG::processSample()
{
boost::mutex::scoped_lock lock(m_Mutex);
while( readIdx == writeIdx )
{
bufferNotEmpty.wait(lock);
}
sample[readIdx] *= 2;
readIdx = (readIdx+1) % BUFFER_SIZE;
++sampleIdx;
bufferNotFull.notify_one();
}
I already included the placeholders.hpp header file but it still doesn't compile. If I replace the _1 with 0, then it will work. But this will initialize the thread function with 0, which is not what I want. Any ideas on how to make this work?
Move the creation to the initialization list:
m_ThreadWrite(boost::bind(&ECG::fillSample, this, _1)), ...
thread object is not copyable, and your compiler doesn't support its move constructor.

Resources