I want to develop a logger class. So I decided put all related code to the read operation in the
dataLogger class.
In the dataLogger with a thread, I want to able write data in a buffer, which named “queue_”. In main class that contains an object of dataLogger, I want to able read from the “queue_” with another thread. Therefore, I use shared_pointer to access the buffer.
Is it possible to use one mutex to manage read and write operation?
Actually, I want to pass the mutex witch created in main class to the dataLogger class.
I used QtGuiApplication to illustrate my problem.
In main.cpp
#include "QtGuiApplication8.h"
#include <QtWidgets/QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
QtGuiApplication8 w;
w.show();
return a.exec();
}
In QtGuiApplication8.h
#pragma once
#include <QtWidgets/QMainWindow>
#include "ui_QtGuiApplication8.h"
#include <thread>
#include <mutex>
#include <vector>
#include "dataLogger.h"
using namespace std;
class QtGuiApplication8 : public QMainWindow
{
Q_OBJECT
public:
QtGuiApplication8(QWidget *parent = Q_NULLPTR);
private:
Ui::QtGuiApplication8Class ui;
std::thread thread_;
bool thread_flag = false;
void thread_fn();
std::mutex mutex_;
shared_ptr < vector<std::shared_ptr<vector<uint8_t>>>> queue_;
dataLogger dataLogger_;
};
In QtGuiApplication8.cpp
#include "QtGuiApplication8.h"
QtGuiApplication8::QtGuiApplication8(QWidget *parent)
: QMainWindow(parent)
{
ui.setupUi(this);
queue_ = make_shared< vector<std::shared_ptr<vector<uint8_t>>>>();
dataLogger_.setQueue(queue_);
// setMutex(mutex_); //I want same thing like this line !
dataLogger_.run();
thread_flag = true;
thread_ = std::thread(&QtGuiApplication8::thread_fn, this);
}
void QtGuiApplication8::thread_fn()
{
while (thread_flag)
{
while (queue_->size() != 0)
{
{
std::lock_guard<std::mutex> f(mutex_);
// auto scan_raw = queue_->back(); // at this line I want to read queue_
}
}
Sleep(20);
}
}
dataLogger.h
#pragma once
#include <thread>
#include <mutex>
#include <vector>
#ifdef _WIN32
#include <Windows.h>
#else
#include <unistd.h>
#endif
using namespace std;
class dataLogger
{
public:
void setQueue(shared_ptr<vector<shared_ptr<vector<uint8_t>>>> q) { queue_ = q; };
//void setMutex(mutex* m) { mutex_ = *m; }; //I want same thing like this line !
void run();
void stop();
private:
std::thread thread_;
bool thread_flag = false;
void thread_fn();
std::mutex mutex_;
shared_ptr<vector<std::shared_ptr<vector<uint8_t>>>> queue_;
};
dataLogger.cpp
#include "dataLogger.h"
void dataLogger::run()
{
thread_flag = true;
thread_ = std::thread(&dataLogger::thread_fn, this);
}
void dataLogger::stop()
{
thread_flag = false;
if (thread_.joinable())
thread_.join();
}
void dataLogger::thread_fn()
{
std::shared_ptr<vector<uint8_t>> rawData_;
rawData_ = std::make_shared<vector<uint8_t>>(10);
vector<uint8_t> sasaa;
while (thread_flag)
{
{
std::lock_guard<std::mutex> f(mutex_);
for (size_t i = 0; i < 10; i++)
rawData_->at(i) = i; // simulation data source
queue_->push_back(rawData_);
}
rawData_ = std::make_shared<vector<uint8_t>>(10);
Sleep(20);
}
}
Related
I want to make my application multithreaded. When I added 2 separate independent threads I have got runtime error message. I can't find the solution. Perhaps someone may help.
Here is link to runtime error image https://postimg.org/image/aasqn2y7b/
threads.h
#include <thread>
#include <atomic>
#include <chrono>
#include <iostream>
class Threads
{
public:
Threads() : m_threadOne(), m_threadTwo(), m_stopper(false) { }
~Threads() {
m_stopper.exchange(true);
if (m_threadOne.joinable()) m_threadOne.join();
if (m_threadTwo.joinable()) m_threadTwo.join();
}
void startThreadOne() {
m_threadOne = std::thread([this]() {
while (true) {
if (m_stopper.load()) break;
std::cout << "Thread 1" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});
}
void startThreadTwo() {
m_threadOne = std::thread([this]() {
while (true) {
if (m_stopper.load()) break;
std::cout << "Thread 2" << std::endl;
std::this_thread::sleep_for(std::chrono::seconds(1));
}
});
}
private:
std::thread m_threadOne;
std::thread m_threadTwo;
std::atomic<bool> m_stopper;
};
mainwindow.h
#include "threads.h"
#include <QMainWindow>
#include "ui_mainwindow.h"
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0) : QMainWindow(parent), ui(new Ui::MainWindow), m_threads() {
ui->setupUi(this);
m_threads.startThreadOne();
m_threads.startThreadTwo();
}
~MainWindow() { delete ui; }
private:
Ui::MainWindow *ui;
Threads m_threads;
};
main.cpp
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
Your start thread two is broken:
m_threadOne = std::thread([this]() { ... });
After starting thread one, m_thread_one gets another thread assigned. However, the thread one is not joined, hence the termination.
I'm trying to send some data over serial port using QSerialPort class. Sending data from the same parent class every time works well. But when I'm trying to send data using another thread QSerialPort it doesn't. I used serial port monitor to watch the data and it showed nothing.
Code is looks like this:
#include <QSerialPort>
#include <QObject>
#include <QDebug>
#include <QCoreApplication>
#include <thread>
#include <mutex>
#include <list>
#include <memory>
class Message {
public:
bool isSent;
bool isProcessed;
int data;
Message(int d) :
data(d),
isSent(false),
isProcessed(false) {
}
};
class SerialClass : public QObject {
Q_OBJECT
public:
SerialClass(unsigned short portNumber, unsigned int baudrate, QObject *parent = 0) :
_portNumber(portNumber),
_baudrate(baudrate),
_serialPort(new QSerialPort(this)),
_messages(),
_writeThread(nullptr),
QObject(parent) {
_serialPort->setPortName(QString("COM%1").arg(_portNumber));
_serialPort->setBaudRate(baudrate);
_serialPort->setDataBits(QSerialPort::DataBits::Data8);
_serialPort->setParity(QSerialPort::Parity::NoParity);
_serialPort->setStopBits(QSerialPort::StopBits::OneStop);
}
void start() {
if (!_serialPort->open(QIODevice::ReadWrite)) {
qDebug() << "Couldn't open serial port";
return;
}
auto *m = &_messages;
auto *p = &_enableProcessing;
auto *port = _serialPort.get();
auto *mutex = &_mutex;
_serialPort->write(QString("Hello\r\n").toLocal8Bit());
_writeThread = std::make_unique<std::thread>([m, p, port, mutex]() {
qDebug() << "Work thread started";
while (*p) {
std::this_thread::sleep_for(std::chrono::milliseconds(15));
auto inactiveMessage = std::find_if(m->begin(), m->end(), [](Message &item) {
return !item.isSent;
});
if (inactiveMessage != m->end()) {
mutex->lock();
qDebug() << "Written" << port->write(QString("data %1\r\n").arg(inactiveMessage->data).toLocal8Bit());
inactiveMessage->isSent = true;
mutex->unlock();
}
}
qDebug() << "Work thread stopped";
});
}
void wait() {
if (!_writeThread) {
return;
}
_writeThread->join();
}
void addMessage(Message& msg) {
_mutex.lock();
_messages.push_back(msg);
_mutex.unlock();
}
private:
unsigned short _portNumber;
unsigned int _baudrate;
std::unique_ptr<QSerialPort> _serialPort;
std::unique_ptr<std::thread> _writeThread;
std::list<Message> _messages;
bool _enableProcessing;
std::mutex _mutex;
};
int main(int argc, char ** argv) {
QCoreApplication application(argc, argv);
SerialClass serialProcessor(2, 9600, &application);
serialProcessor.addMessage(Message(228));
serialProcessor.addMessage(Message(929));
serialProcessor.addMessage(Message(221424));
serialProcessor.start();
return application.exec();
}
#include "main.moc"
Does it means what the QSerialPort class can not transmit data from another thread? (not QSerialPort thread)
It is recommended not to mix STL and Qt solutions in the same project
QSerialPort can work in any thread
You can see an example of correct using of QThread here: https://stackoverflow.com/a/35673612/4149835
Been looking for awhile and I cant find an answer. All paths are included. I'm referencing a class in another namespace in the class I'm creating.
I'm getting the following error:
src/app/Application.h:30:9: error: 'drv' does not name a type
Code Below. Any help is appreciated!
Main.cpp
int main(int argc, char** argv) {
app::Application program;
program.run();
return 0;
}
LEDs.h
#ifndef LEDS_H
#define LEDS_H
namespace drv {
class LEDs {
public:
LEDs();
void InitLEDs(void);
void SetLEDs(const uint8_t value);
private:
static const uint8_t NUM_LEDs = 5;
};
}
#endif /* LEDS_H */
Application.h
#ifndef APPLICATION_H
#define APPLICATION_H
namespace app {
enum State {
NORMAL = 0,
ZONE,
PAIRING,
STUCK,
BATT,
OFF
};
class Application {
public:
Application();
void run(void);
void execute_loop(void);
private:
bool IDLE;
State STATE;
drv::LEDs Leds; // LINE 30
};
}
#endif // APPLICATION_H
Application.cpp
#include "stdint.h"
#include "stdbool.h"
#include "../drv/LEDs.h"
#include "Application.h"
namespace app {
Application::Application() {
IDLE = false;
STATE = NORMAL;
}
void Application::run(void) {
Leds.InitLEDs();
while(1)
{
if(IDLE) {
PowerSaveIdle();
}
else {
execute_loop();
}
}
}
void Application::execute_loop(void)
{
}
}
LEDs.cpp
#include <stdint.h>
#include "LEDs.h"
namespace drv {
LEDs::LEDs() {
}
void LEDs::InitLEDs() {
SetLEDs(0xff);
}
void LEDs::SetLEDs(const uint8_t value) {
//Removed for readability
}
}
You're missing an #include ... line in Application.h. At the top of that file (or just after the inclusion guards) add the line
#include "LEDs.h"
I have written a QT - webkit application. this application fires a callback when my pSeudo driver gets the character 'l'. However, the application crashes during a firecallback - it says - QObject::setParent: Cannot set parent, new parent is in a different thread. I don't know to fix this, I tried doing moveToThread, but it doesn't help. Please help me here.
#include <QtGui/QApplication>
#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>
#include <QThread>
#include <unistd.h>
#include <fcntl.h>
class DemoThread;
class MyJavaScriptOperations : public QObject {
Q_OBJECT
public:
QWebView *view;
DemoThread *m_pDemoThread;
MyJavaScriptOperations();
void firecb();
bool slot_installed;
signals:
void alert_script_signal();
public slots:
void JS_ADDED();
void loadFinished(bool);
private:
};
class DemoThread : public QThread {
public:
DemoThread( MyJavaScriptOperations *pJavascriptOp);
protected:
void run();
private :
MyJavaScriptOperations *m_pJavascriptOp;
};
DemoThread::DemoThread(MyJavaScriptOperations *pJavascriptOp):m_pJavascriptOp(pJavascriptOp)
{
}
void DemoThread:: run()
{
int filedesc = open("/dev/pSeudoDrv", O_RDONLY);
if(filedesc < 0)
{
qDebug()<<"Couldn't open Driver.";
}
unsigned char buff;
while(1)
{
read(filedesc,&buff, 1);
qDebug()<<"The code received is "<< buff;
if ( (m_pJavascriptOp->slot_installed == true) && (buff == 166))
{
m_pJavascriptOp->firecb();
}
qDebug()<<"Running Thread.";
sleep(6);
}
}
void MyJavaScriptOperations::JS_ADDED()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", this);
}
void MyJavaScriptOperations::loadFinished(bool oper)
{
qDebug()<<__PRETTY_FUNCTION__<< oper;
slot_installed = true;
// firecb();
}
void MyJavaScriptOperations::firecb()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->evaluateJavaScript("JavaScript_function()");
}
MyJavaScriptOperations::MyJavaScriptOperations()
{
qDebug()<<__PRETTY_FUNCTION__;
view = new QWebView();
view->resize(400, 500);
connect(view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(JS_ADDED()));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
view->load(QUrl("./index.html"));
view->show();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyJavaScriptOperations *jvs = new MyJavaScriptOperations;
DemoThread *thread = new DemoThread(jvs);
jvs->moveToThread(thread);
thread->start();
return a.exec();
}
#include "main.moc"
This is the crash-error I get -
./QT_DEMO
MyJavaScriptOperations::MyJavaScriptOperations()
loaded the Generic plugin
The code received is 156
Running Thread.
The code received is 166
void MyJavaScriptOperations::firecb()
QObject::setParent: Cannot set parent, new parent is in a different thread
There are few articles on internet how to make multithreaded applications in Qt. Best explanation can be found here:
http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
You could read also other articles:
https://www.qt.io/blog/2010/06/17/youre-doing-it-wrong
http://mayaposch.wordpress.com/2011/11/01/how-to-really-truly-use-qthreads-the-full-explanation/
Well, I got a solution for my problem. Please tell me, am I complicating the solution.
I am using signal and slot. The thread will emit the signal and the slot of other class will emit the callback to the Qtwebkit - the javascript function. IS it right?
Because, I have suggestion using event loop - exec().
#include <QtGui/QApplication>
#include <QApplication>
#include <QDebug>
#include <QWebFrame>
#include <QWebPage>
#include <QWebView>
#include <QThread>
/** for reading my driver **/
#include <unistd.h>
#include <fcntl.h>
class DemoThread;
class MyJavaScriptOperations : public QObject
{
Q_OBJECT
public:
QWebView *view;
DemoThread *m_pDemoThread;
MyJavaScriptOperations();
void firecb();
bool slot_installed;
signals:
void alert_script_signal();
public slots:
void JsAdded();
void alertReceived();
void loadFinished(bool);
private:
};
class DemoThread : public QThread
{
Q_OBJECT
private:
MyJavaScriptOperations *m_pJavascriptOp;
public:
DemoThread( MyJavaScriptOperations *pJavascriptOp);
protected:
void run();
signals:
void alertSendSignal();
};
DemoThread::DemoThread(MyJavaScriptOperations *pJavascriptOp):m_pJavascriptOp(pJavascriptOp)
{
connect(this, SIGNAL(alertSendSignal()), m_pJavascriptOp, SLOT(alertReceived()));
}
void DemoThread:: run()
{
int filedesc = open("/dev/pSeudoDrv", O_RDONLY);
if(filedesc < 0)
{
qDebug()<<"Couldn't open Driver.";
}
unsigned char buff;
while(1)
{
if( 1 != read(filedesc,&buff, 1))
{
qDebug()<<"Read Invalid Data";
}
qDebug()<<"The code received is "<< buff;
/** In my laptop, the 166 means the character 'l' **/
if ( (m_pJavascriptOp->slot_installed == true) && (buff == 166))
{
emit alertSendSignal();
}
qDebug()<<"Running Thread.";
}
}
void MyJavaScriptOperations::JsAdded()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->addToJavaScriptWindowObject("myoperations", this);
}
void MyJavaScriptOperations::loadFinished(bool oper)
{
qDebug()<<__PRETTY_FUNCTION__<< oper;
slot_installed = true;
}
void MyJavaScriptOperations::alertReceived()
{
qDebug()<<"Sending Firecallback now";
firecb();
}
void MyJavaScriptOperations::firecb()
{
qDebug()<<__PRETTY_FUNCTION__;
view->page()->mainFrame()->evaluateJavaScript("JavaScript_function()");
}
MyJavaScriptOperations::MyJavaScriptOperations()
{
qDebug()<<__PRETTY_FUNCTION__;
view = new QWebView();
view->resize(400, 500);
connect(view->page()->mainFrame(), SIGNAL(javaScriptWindowObjectCleared()), this, SLOT(JsAdded()));
connect(view, SIGNAL(loadFinished(bool)), this, SLOT(loadFinished(bool)));
view->load(QUrl("./index.html"));
view->show();
}
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MyJavaScriptOperations *jvs = new MyJavaScriptOperations;
DemoThread *thread = new DemoThread(jvs);
thread->start();
return a.exec();
}
#include "main.moc"
I have encountered some problem that I seem not be able to solve. It may be some silly mistake. I have a class that runs another class's method in a separate QThread 5000msec after the method fires a signal. At least this would be the idea but this is not happening.
#ifndef MOVEME_MPOINTER_HPP
#define MOVEME_MPOINTER_HPP
#include <Windows.h>
#include <WindowsX.h>
#include <QSystemTrayIcon>
#include <QDesktopWidget>
#include <QApplication>
#include <QMainWindow>
#include <QMessageBox>
#include <QByteArray>
#include <QAction>
#include <QCursor>
#include <QThread>
#include <QTimer>
#include <QDebug>
#include <QMenu>
#include <QIcon>
#include <QRect>
#include "worker.hpp"
namespace Ui {
class MoveMe_MPointer;
}
class MoveMe_MPointer : public QMainWindow
{
Q_OBJECT
public:
explicit MoveMe_MPointer(QWidget *parent = 0);
~MoveMe_MPointer();
virtual bool nativeEvent(const QByteArray &eventType, void *message, long *result);
public slots:
void resetTimer();
void closeApplication();
private:
QSharedPointer<QIcon> icon;
QSharedPointer<QSystemTrayIcon> systemtray;
QSharedPointer<QThread> workerThread;
QSharedPointer<Worker> workerObject;
QSharedPointer<QTimer> workerTimer;
QSharedPointer<QCursor> cursor;
};
#endif // MOVEME_MPOINTER_HPP
The implementation of the relevant methods are as follows:
MoveMe_MPointer::MoveMe_MPointer(QWidget *parent) : QMainWindow(parent) {
icon = QSharedPointer<QIcon>(new QIcon("://appicon"));
systemtray = QSharedPointer<QSystemTrayIcon>(new QSystemTrayIcon);
// Create cursor
cursor = QSharedPointer<QCursor>(new QCursor(Qt::ForbiddenCursor));
systemtray->setIcon(*icon.data());
systemtray->setVisible(true);
workerThread = QSharedPointer<QThread>(new QThread());
workerObject = QSharedPointer<Worker> (new Worker ());
workerObject->setX(100);
workerObject->setY(100);
workerObject->moveToThread(workerThread.data());
workerTimer = QSharedPointer<QTimer>(new QTimer());
QObject::connect(workerThread.data(), SIGNAL(started()), workerObject.data(), SLOT(Work()));
QObject::connect(workerTimer.data(), SIGNAL(timeout()), workerObject.data(), SLOT(Work()));
QObject::connect(workerObject.data(), SIGNAL(Done()), this, SLOT(resetTimer()));
RegisterHotKey((HWND) winId(), 0, MOD_CONTROL, 0x51);
RegisterHotKey((HWND) winId(), 1, MOD_CONTROL | MOD_SHIFT, 0x4D);
}
void MoveMe_MPointer::resetTimer() {
qDebug() << "START";
workerTimer->start(5000);
qDebug() << "STOP";
}
The underlying class:
#ifndef WORKER_HPP
#define WORKER_HPP
#include <Windows.h>
#include <QSharedPointer>
#include <QMouseEvent>
#include <QObject>
#include <QCursor>
#include <QThread>
#include <QDebug>
class Worker : public QObject
{
Q_OBJECT
int x;
int y;
bool stop;
public:
explicit Worker(QObject *parent = 0);
void setX(const int x);
void setY(const int y);
void Stop();
signals:
void Done();
public slots:
void Work();
private:
void doWork();
};
#endif // WORKER_HPP
With the implementation as follows:
#include "worker.hpp"
Worker::Worker(QObject *parent) : QObject(parent) {
stop = false;
}
void Worker::setX(const int x) {
this->x = x;
}
void Worker::setY(const int y) {
this->y = y;
}
void Worker::Stop() {
stop = true;
}
void Worker::Work() {
doWork();
}
void Worker::doWork() {
int _x = 50;
INPUT input;
ZeroMemory(&input, sizeof(input));
input.type = INPUT_MOUSE;
input.mi.mouseData = 0;
input.mi.dwFlags = MOUSEEVENTF_MOVE;
for (int dx = 0; dx < _x && !stop; ++dx) {
input.mi.dx = +1;
input.mi.dy = +1;
SendInput(1, &input, sizeof(input));
QThread::msleep(10);
}
QThread::msleep(100);
for (int dx = 0; dx < _x && !stop; ++dx) {
input.mi.dx = -1;
input.mi.dy = -1;
SendInput(1, &input, sizeof(input));
QThread::msleep(10);
}
QThread::msleep(100);
emit Done();
}
Whenever my application receives the Done signal my resetTimer slot gets executed but the interesting part is. It times out immediately and does not wait even a second. What am i missing?