commit 5d3ed2294fcbda27bb78e8da4875acbda30f1eb5 Author: Jan Grewe Date: Fri Aug 31 18:20:47 2018 +0200 initial diff --git a/DataService.pro b/DataService.pro new file mode 100644 index 0000000..7d9cd69 --- /dev/null +++ b/DataService.pro @@ -0,0 +1,48 @@ +#------------------------------------------------- +# +# Project created by QtCreator 2018-08-29T14:47:02 +# +#------------------------------------------------- + +QT += core gui charts + +greaterThan(QT_MAJOR_VERSION, 4): QT += widgets + +TARGET = DataService +TEMPLATE = app + +# The following define makes your compiler emit warnings if you use +# any feature of Qt which has been marked as deprecated (the exact warnings +# depend on your compiler). Please consult the documentation of the +# deprecated API in order to know how to port your code away from it. +DEFINES += QT_DEPRECATED_WARNINGS + +# You can also make your code fail to compile if you use deprecated APIs. +# In order to do so, uncomment the following line. +# You can also select to disable deprecated APIs only up to a certain version of Qt. +#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000 # disables all the APIs deprecated before Qt 6.0.0 + + +SOURCES += \ + main.cpp \ + mainwindow.cpp \ + dataservice.cpp \ + dataqueue.cpp \ + dataloader.cpp \ + dataresult1d.cpp \ + datarequest.cpp \ + converttoseries.cpp + +HEADERS += \ + mainwindow.h \ + dataservice.h \ + dataqueue.h \ + dataloader.h \ + dataresult1d.h \ + datarequest.h \ + converttoseries.h + +FORMS += \ + mainwindow.ui + +unix|win32: LIBS += -lnix diff --git a/DataService.pro.user b/DataService.pro.user new file mode 100644 index 0000000..b1cea73 --- /dev/null +++ b/DataService.pro.user @@ -0,0 +1,336 @@ + + + + + + EnvironmentId + {8b523b8d-f5ce-4be4-a9bd-780a0aec766f} + + + ProjectExplorer.Project.ActiveTarget + 0 + + + ProjectExplorer.Project.EditorSettings + + true + false + true + + Cpp + + CppGlobal + + + + QmlJS + + QmlJSGlobal + + + 2 + UTF-8 + false + 4 + false + 80 + true + true + 1 + true + false + 0 + true + true + 0 + 8 + true + 1 + true + true + true + false + + + + ProjectExplorer.Project.PluginSettings + + + + ProjectExplorer.Project.Target.0 + + Desktop + Desktop + {d7263c99-5355-4486-be71-56523c5d259f} + 0 + 0 + 0 + + /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Debug + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Debug + Debug + Qt4ProjectManager.Qt4BuildConfiguration + 2 + true + + + /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Release + + + true + qmake + + QtProjectManager.QMakeBuildStep + false + + false + false + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Release + Release + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + + /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Profile + + + true + qmake + + QtProjectManager.QMakeBuildStep + true + + false + true + false + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + false + + + + 2 + Build + + ProjectExplorer.BuildSteps.Build + + + + true + Make + + Qt4ProjectManager.MakeStep + + -w + -r + + true + clean + + + 1 + Clean + + ProjectExplorer.BuildSteps.Clean + + 2 + false + + Profile + Profile + Qt4ProjectManager.Qt4BuildConfiguration + 0 + true + + 3 + + + 0 + Deploy + + ProjectExplorer.BuildSteps.Deploy + + 1 + Deploy Configuration + + ProjectExplorer.DefaultDeployConfiguration + + 1 + + + false + false + 1000 + + true + + false + false + false + false + true + 0.01 + 10 + true + 1 + 25 + + 1 + true + false + true + valgrind + + 0 + 1 + 2 + 3 + 4 + 5 + 6 + 7 + 8 + 9 + 10 + 11 + 12 + 13 + 14 + + 2 + + DataService + + Qt4ProjectManager.Qt4RunConfiguration:/home/grewe/zwischenlager/event_queue/DataService/DataService.pro + true + + DataService.pro + false + + /home/grewe/zwischenlager/event_queue/build-DataService-Desktop-Debug + 3768 + false + true + false + false + true + + 1 + + + + ProjectExplorer.Project.TargetCount + 1 + + + ProjectExplorer.Project.Updater.FileVersion + 18 + + + Version + 18 + + diff --git a/converttoseries.cpp b/converttoseries.cpp new file mode 100644 index 0000000..a539292 --- /dev/null +++ b/converttoseries.cpp @@ -0,0 +1,26 @@ +#include "converttoseries.h" +using namespace QtCharts; + +ConvertToSeries::ConvertToSeries(QObject *parent) : QObject(parent) +{ + +} + +void ConvertToSeries::run() { + mutex.lock(); + if (dataPresent) { + for (size_t i = 0; i < data.xdata.size(); ++i) { + this->series->append(data.xdata[i], data.ydata[i]); + } + emit dataConverted(series, QString::fromStdString(data.entityId)); + } + mutex.unlock(); +} + +void ConvertToSeries::setData(QLineSeries *series, const DataResult1D &data) { + mutex.lock(); + this->series = series; + this->data = data; + this->dataPresent = true; + mutex.unlock(); +} diff --git a/converttoseries.h b/converttoseries.h new file mode 100644 index 0000000..97d19e5 --- /dev/null +++ b/converttoseries.h @@ -0,0 +1,33 @@ +#ifndef CONVERTTOSERIES_H +#define CONVERTTOSERIES_H + +#include +#include +#include +#include +#include "dataresult1d.h" + +using namespace QtCharts; + +class ConvertToSeries : public QObject, public QRunnable { + Q_OBJECT +public: + explicit ConvertToSeries(QObject *parent = nullptr); + +private: + QMutex mutex; + bool dataPresent = false; + DataResult1D data; + QLineSeries *series; + + void run() override; + +public: + void setData(QLineSeries *series, const DataResult1D &data); + +signals: + void dataConverted(QLineSeries *series, QString entityId); + +}; + +#endif // CONVERTTOSERIES_H diff --git a/dataloader.cpp b/dataloader.cpp new file mode 100644 index 0000000..a2c42d8 --- /dev/null +++ b/dataloader.cpp @@ -0,0 +1,16 @@ +#include "dataloader.h" +#include + +DataLoader::DataLoader() +{ + +} + +DataResult1D DataLoader::doLoad(const DataRequest &request) { + std::vector x, y; + x = request.array.getDimension(1).asSampledDimension().axis(request.count[0], request.start[0]); + request.array.getData(y, request.count, request.start); + + DataResult1D res(request.id, request.array.id(), x, y); + return res; +} diff --git a/dataloader.h b/dataloader.h new file mode 100644 index 0000000..cf4b085 --- /dev/null +++ b/dataloader.h @@ -0,0 +1,20 @@ +#ifndef DATALOADER_H +#define DATALOADER_H + +#include +#include "datarequest.h" +#include "dataresult1d.h" + +class DataLoader : public QObject +{ + Q_OBJECT +public: + DataLoader(); + +public slots: + DataResult1D doLoad(const DataRequest &request); +}; + + + +#endif // DATALOADER_H diff --git a/dataqueue.cpp b/dataqueue.cpp new file mode 100644 index 0000000..ed5fa43 --- /dev/null +++ b/dataqueue.cpp @@ -0,0 +1,54 @@ +#include "dataqueue.h" + + +DataQueue::DataQueue(QObject *parent) : + QThread(parent), stopped(false) +{} + + +DataQueue::~DataQueue(){ +} + +void DataQueue::run() { + mutex.lock(); + bool stop = stopped || (requestQueue.size() == 0); + mutex.unlock(); + while (!stop) { + mutex.lock(); + if (requestQueue.size() > 0) { + DataResult1D data = loader->doLoad(requestQueue.front()); + resultMap.insert(std::pair(data.id, data)); + emit resultReady(QString::fromStdString(data.id)); + requestQueue.pop(); + stop = requestQueue.size() == 0 || stopped; + } + mutex.unlock(); + } +} + +void DataQueue::requestData(const nix::DataArray &array, const nix::NDSize &count, const nix::NDSize &offset, std::string &requestId) { + requestId = nix::util::createId(); + DataRequest dr(requestId, array, count, offset); + mutex.lock(); + requestQueue.push(dr); + mutex.unlock(); + start(); +} + +void DataQueue::stop() { + mutex.lock(); + stopped = true; + mutex.unlock(); +} + +DataResult1D DataQueue::getData(QString requestId) { + DataResult1D ret; + mutex.lock(); + std::map::iterator it = resultMap.find(requestId.toStdString()); + if (it != resultMap.end()) { + ret = it->second; + resultMap.erase(it); + } + mutex.unlock(); + return ret; +} diff --git a/dataqueue.h b/dataqueue.h new file mode 100644 index 0000000..a583253 --- /dev/null +++ b/dataqueue.h @@ -0,0 +1,42 @@ +#ifndef DATAQUEUE_H +#define DATAQUEUE_H + +#include +#include +#include +#include +#include +#include +#include + +#include "dataloader.h" +#include "dataresult1d.h" +#include "datarequest.h" + +class DataQueue : public QThread +{ + Q_OBJECT +public: + DataQueue(QObject *parent = 0); + ~DataQueue(); + + void run() override; + void stop(); + DataResult1D getData(QString requestId); + +signals: + void resultReady(QString requestId); + +public slots: + void requestData(const nix::DataArray &array, const nix::NDSize &count, const nix::NDSize &offset, std::string &requestId); + + +private: + std::queue requestQueue; + std::map resultMap; + QMutex mutex; + DataLoader *loader; + bool stopped; +}; + +#endif // DATAQUEUE_H diff --git a/datarequest.cpp b/datarequest.cpp new file mode 100644 index 0000000..3a6cbd1 --- /dev/null +++ b/datarequest.cpp @@ -0,0 +1,5 @@ +#include "datarequest.h" + +DataRequest::DataRequest(const std::string &requestId, const nix::DataArray &array, const nix::NDSize &count, const nix::NDSize &start) + : id(requestId), array(array), count(count), start(start) +{} diff --git a/datarequest.h b/datarequest.h new file mode 100644 index 0000000..e051568 --- /dev/null +++ b/datarequest.h @@ -0,0 +1,16 @@ +#ifndef DATAREQUEST_H +#define DATAREQUEST_H + +#include + +class DataRequest +{ +public: + DataRequest(const std::string &requestId, const nix::DataArray &array, const nix::NDSize &count, const nix::NDSize &start); + + std::string id; + nix::DataArray array; + nix::NDSize count, start; +}; + +#endif // DATAREQUEST_H diff --git a/dataresult1d.cpp b/dataresult1d.cpp new file mode 100644 index 0000000..0a87513 --- /dev/null +++ b/dataresult1d.cpp @@ -0,0 +1,6 @@ +#include "dataresult1d.h" + +DataResult1D::DataResult1D(const std::string &request_id, const std::string &entityId, const std::vector &x, const std::vector &y) + : id(request_id), entityId(entityId), xdata(x), ydata(y) +{} + diff --git a/dataresult1d.h b/dataresult1d.h new file mode 100644 index 0000000..baa5fdd --- /dev/null +++ b/dataresult1d.h @@ -0,0 +1,18 @@ +#ifndef DATARESULT1D_H +#define DATARESULT1D_H + +#include +#include + +class DataResult1D +{ +public: + DataResult1D(){}; + DataResult1D(const std::string &request_id, const std::string &entityId, const std::vector &x, const std::vector &y); + + std::string id, entityId; + std::vector xdata; + std::vector ydata; +}; + +#endif // DATARESULT1D_H diff --git a/dataservice.cpp b/dataservice.cpp new file mode 100644 index 0000000..2e5b660 --- /dev/null +++ b/dataservice.cpp @@ -0,0 +1,20 @@ +#include "dataservice.h" + + +DataService::DataService(QObject *parent): + QObject(parent) +{} + + +void DataService::doWork( ) { + QString result; + size_t count = 0; + for (size_t i = 1; i < 100000000; ++i){ + count++; + } + + /* ... here is the expensive or blocking operation ... */ + emit resultReady(); +} + + diff --git a/dataservice.h b/dataservice.h new file mode 100644 index 0000000..6dc75a7 --- /dev/null +++ b/dataservice.h @@ -0,0 +1,19 @@ +#ifndef DATASERVICE_H +#define DATASERVICE_H + +#include + +class DataService : public QObject +{ + Q_OBJECT +public: + explicit DataService(QObject *parent = nullptr); + +signals: + void resultReady(); + +public slots: + void doWork(); +}; + +#endif // DATASERVICE_H diff --git a/main.cpp b/main.cpp new file mode 100644 index 0000000..4cc5943 --- /dev/null +++ b/main.cpp @@ -0,0 +1,13 @@ +#include "mainwindow.h" +#include +#include "dataresult1d.h" + + +int main(int argc, char *argv[]) +{ + QApplication a(argc, argv); + MainWindow w; + w.show(); + + return a.exec(); +} diff --git a/mainwindow.cpp b/mainwindow.cpp new file mode 100644 index 0000000..05c9ca3 --- /dev/null +++ b/mainwindow.cpp @@ -0,0 +1,107 @@ +#include "mainwindow.h" +#include "ui_mainwindow.h" +#include "converttoseries.h" +#include + +using namespace QtCharts; + +MainWindow::MainWindow(QWidget *parent) : + QMainWindow(parent), + ui(new Ui::MainWindow) +{ + ui->setupUi(this); + /* + dataService = new DataService(); + dataService->moveToThread(&dataServiceThread); + connect(&dataServiceThread, &QThread::finished, dataService, &QObject::deleteLater); + connect(ui->goBtn, SIGNAL(clicked(bool)), dataService, SLOT(doWork())); + connect(dataService, SIGNAL(resultReady()), this, SLOT(handleResult())); + dataServiceThread.start(); + */ + connect(&dataQueue, SIGNAL(resultReady(QString)), this, SLOT(dataReady(QString))); + //connect(&dataQueue, SIGNAL(finished()), &dataQueue, SLOT(deleteLater())); + DataLoader *loader = new DataLoader(); + loader->moveToThread(&dataQueue); + dataQueue.start(); + + connect(ui->requestDataBtn, SIGNAL(clicked(bool)), this, SLOT(requestData())); + file = nix::File::open("/home/grewe/zwischenlager/2017-08-17-af-invivo-1/2017-08-17-af-invivo-1.nix", + nix::FileMode::ReadOnly); + + //file = nix::File::open("/Users/jan/zwischenlager/threading_test/event_queue/DataService/data/2017-08-17-af-invivo-1.nix", + // nix::FileMode::ReadOnly); + nix::Block b = file.getBlock(0); + this->voltage = b.getDataArray("V-1"); + this->eod = b.getDataArray("EOD"); + + voltageChart = new QChart(); + voltageChart->legend()->hide(); + //voltageChart->createDefaultAxes(); + + eodChart = new QChart(); + eodChart->legend()->hide(); + //eodChart->createDefaultAxes(); + + + chartMap.insert(std::pair(voltage.id(), voltageChart)); + chartMap.insert(std::pair(eod.id(), eodChart)); + + voltageChart->setTitle(QString::fromStdString(this->voltage.name())); + eodChart->setTitle(QString::fromStdString(this->eod.name())); + QMargins margins = voltageChart->margins(); + int marg1 = margins.left(); + margins.setLeft(marg1 * 4); + eodChart->setMargins(margins); + voltageView = new QtCharts::QChartView(voltageChart); + eodView = new QtCharts::QChartView(eodChart); + + voltageView->setRenderHint(QPainter::Antialiasing); + eodView->setRenderHint(QPainter::Antialiasing); + ui->vbox->addWidget(voltageView); + ui->vbox->addWidget(eodView); +} + + +MainWindow::~MainWindow() { + if (file) { + file.close(); + } + //dataServiceThread.quit(); + //dataServiceThread.wait(); + dataQueue.stop(); + dataQueue.quit(); + dataQueue.wait(); + delete ui; +} + + +void MainWindow::dataReady(QString requestId) { + DataResult1D data = dataQueue.getData(requestId); + if (data.id.empty()) { + return; + } + ConvertToSeries *task = new ConvertToSeries(); + QLineSeries *series = new QLineSeries(); + task->setData(series, data); + connect(task, SIGNAL(dataConverted(QLineSeries*,QString)), this, SLOT(dataConverted(QLineSeries*,QString))); + QThreadPool::globalInstance()->start(task); +} + + +void MainWindow::dataConverted(QLineSeries *series, QString entityId) { + QPen pen = series->pen(); + pen.setWidth(1); + series->setPen(pen); + chartMap[entityId.toStdString()]->addSeries(series); +} + + +void MainWindow::requestData() { + if (voltage && eod) { + nix::NDSize count(1, 10000); + nix::NDSize start(1, 0); + std::string vId, eodId; + dataQueue.requestData(voltage, count, start, vId); + dataQueue.requestData(eod, count, start, eodId); + } +} diff --git a/mainwindow.h b/mainwindow.h new file mode 100644 index 0000000..506e7f1 --- /dev/null +++ b/mainwindow.h @@ -0,0 +1,46 @@ +#ifndef MAINWINDOW_H +#define MAINWINDOW_H + +#include +//#include +#include +#include + +#include "dataservice.h" +#include "dataqueue.h" +#include "dataresult1d.h" + +Q_DECLARE_METATYPE(DataResult1D) + +namespace Ui { +class MainWindow; +} + +class MainWindow : public QMainWindow +{ + Q_OBJECT + +public: + explicit MainWindow(QWidget *parent = 0); + ~MainWindow(); + +public slots: + void requestData(); + void dataReady(QString requestId); + void dataConverted(QLineSeries *series, QString entityId); + +private: + Ui::MainWindow *ui; + //QThread dataServiceThread; + //DataService *dataService; + DataQueue dataQueue; + nix::DataArray voltage, eod; + nix::File file; + QtCharts::QChartView *voltageView; + QtCharts::QChartView *eodView; + QtCharts::QChart *voltageChart; + QtCharts::QChart *eodChart; + std::map chartMap; +}; + +#endif // MAINWINDOW_H diff --git a/mainwindow.ui b/mainwindow.ui new file mode 100644 index 0000000..8b45b0c --- /dev/null +++ b/mainwindow.ui @@ -0,0 +1,57 @@ + + + MainWindow + + + + 0 + 0 + 400 + 300 + + + + MainWindow + + + + + + + 2 + + + + + + + request data + + + + + + + + + 0 + 0 + 400 + 28 + + + + + + TopToolBarArea + + + false + + + + + + + +