##// END OF EJS Templates
Merge branch 'feature/ThreadFix' into develop
perrinel -
r371:684b9afd5f2a merge
parent child
Show More
@@ -1,8 +1,9
1 1 #ifndef SCIQLOP_ARRAYDATA_H
2 2 #define SCIQLOP_ARRAYDATA_H
3 3
4 #include <QReadLocker>
5 #include <QReadWriteLock>
4 6 #include <QVector>
5
6 7 /**
7 8 * @brief The ArrayData class represents a dataset for a data series.
8 9 *
@@ -22,10 +23,22 public:
22 23 template <int D = Dim, typename = std::enable_if_t<D == 1> >
23 24 explicit ArrayData(int nbColumns) : m_Data{1, QVector<double>{}}
24 25 {
26 QWriteLocker locker(&m_Lock);
25 27 m_Data[0].resize(nbColumns);
26 28 }
27 29
28 30 /**
31 * Ctor for a unidimensional ArrayData
32 * @param nbColumns the number of values the ArrayData will hold
33 */
34 explicit ArrayData(const ArrayData &other)
35 {
36 QReadLocker otherLocker(&other.m_Lock);
37 QWriteLocker locker(&m_Lock);
38 m_Data = other.m_Data;
39 }
40
41 /**
29 42 * Sets a data at a specified index. The index has to be valid to be effective
30 43 * @param index the index to which the data will be set
31 44 * @param data the data to set
@@ -34,6 +47,7 public:
34 47 template <int D = Dim, typename = std::enable_if_t<D == 1> >
35 48 void setData(int index, double data) noexcept
36 49 {
50 QWriteLocker locker(&m_Lock);
37 51 if (index >= 0 && index < m_Data.at(0).size()) {
38 52 m_Data[0].replace(index, data);
39 53 }
@@ -44,8 +58,9 public:
44 58 * @remarks this method is only available for a unidimensional ArrayData
45 59 */
46 60 template <int D = Dim, typename = std::enable_if_t<D == 1> >
47 const QVector<double> &data() const noexcept
61 QVector<double> data() const noexcept
48 62 {
63 QReadLocker locker(&m_Lock);
49 64 return m_Data[0];
50 65 }
51 66
@@ -54,8 +69,9 public:
54 69 * @remarks this method is only available for a unidimensional ArrayData
55 70 */
56 71 template <int D = Dim, typename = std::enable_if_t<D == 1> >
57 const QVector<double> &data(double tStart, double tEnd) const noexcept
72 QVector<double> data(double tStart, double tEnd) const noexcept
58 73 {
74 QReadLocker locker(&m_Lock);
59 75 return m_Data.at(tStart);
60 76 }
61 77
@@ -63,20 +79,30 public:
63 79 template <int D = Dim, typename = std::enable_if_t<D == 1> >
64 80 void merge(const ArrayData<1> &arrayData)
65 81 {
82 QWriteLocker locker(&m_Lock);
66 83 if (!m_Data.empty()) {
84 QReadLocker otherLocker(&arrayData.m_Lock);
67 85 m_Data[0] += arrayData.data();
68 86 }
69 87 }
70 88
71 89 template <int D = Dim, typename = std::enable_if_t<D == 1> >
72 int size()
90 int size() const
73 91 {
92 QReadLocker locker(&m_Lock);
74 93 return m_Data[0].size();
75 94 }
76 95
96 void clear()
97 {
98 QWriteLocker locker(&m_Lock);
99 m_Data.clear();
100 }
101
77 102
78 103 private:
79 104 QVector<QVector<double> > m_Data;
105 mutable QReadWriteLock m_Lock;
80 106 };
81 107
82 108 #endif // SCIQLOP_ARRAYDATA_H
@@ -6,9 +6,10
6 6
7 7 #include <QLoggingCategory>
8 8
9 #include <QReadLocker>
10 #include <QReadWriteLock>
9 11 #include <memory>
10 12
11
12 13 Q_DECLARE_LOGGING_CATEGORY(LOG_DataSeries)
13 14 Q_LOGGING_CATEGORY(LOG_DataSeries, "DataSeries")
14 15
@@ -38,12 +39,19 public:
38 39 /// @sa IDataSeries::valuesUnit()
39 40 Unit valuesUnit() const override { return m_ValuesUnit; }
40 41
42 void clear()
43 {
44 m_XAxisData->clear();
45 m_ValuesData->clear();
46 }
47
41 48 /// @sa IDataSeries::merge()
42 49 void merge(IDataSeries *dataSeries) override
43 50 {
44 51 if (auto dimDataSeries = dynamic_cast<DataSeries<Dim> *>(dataSeries)) {
45 52 m_XAxisData->merge(*dimDataSeries->xAxisData());
46 53 m_ValuesData->merge(*dimDataSeries->valuesData());
54 dimDataSeries->clear();
47 55 }
48 56 else {
49 57 qCWarning(LOG_DataSeries())
@@ -51,6 +59,10 public:
51 59 }
52 60 }
53 61
62 virtual void lockRead() { m_Lock.lockForRead(); }
63 virtual void lockWrite() { m_Lock.lockForWrite(); }
64 virtual void unlock() { m_Lock.unlock(); }
65
54 66 protected:
55 67 /// Protected ctor (DataSeries is abstract)
56 68 explicit DataSeries(std::shared_ptr<ArrayData<1> > xAxisData, const Unit &xAxisUnit,
@@ -88,6 +100,8 private:
88 100 Unit m_XAxisUnit;
89 101 std::shared_ptr<ArrayData<Dim> > m_ValuesData;
90 102 Unit m_ValuesUnit;
103
104 QReadWriteLock m_Lock;
91 105 };
92 106
93 107 #endif // SCIQLOP_DATASERIES_H
@@ -51,6 +51,10 public:
51 51 virtual void merge(IDataSeries *dataSeries) = 0;
52 52
53 53 virtual std::unique_ptr<IDataSeries> clone() const = 0;
54
55 virtual void lockRead() = 0;
56 virtual void lockWrite() = 0;
57 virtual void unlock() = 0;
54 58 };
55 59
56 60 // Required for using shared_ptr in signals/slots
@@ -3,6 +3,9
3 3 #include <Data/IDataSeries.h>
4 4 #include <Data/SqpDateTime.h>
5 5
6 #include <QReadWriteLock>
7 #include <QThread>
8
6 9 Q_LOGGING_CATEGORY(LOG_Variable, "Variable")
7 10
8 11 struct Variable::VariablePrivate {
@@ -57,6 +60,7 void Variable::setDateTime(const SqpDateTime &dateTime) noexcept
57 60
58 61 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
59 62 {
63 qCDebug(LOG_Variable()) << "Variable::setDataSeries" << QThread::currentThread()->objectName();
60 64 if (!dataSeries) {
61 65 /// @todo ALX : log
62 66 return;
@@ -67,8 +71,11 void Variable::setDataSeries(std::shared_ptr<IDataSeries> dataSeries) noexcept
67 71 impl->m_DataSeries = dataSeries->clone();
68 72 }
69 73 else {
74 dataSeries->lockWrite();
75 impl->m_DataSeries->lockWrite();
70 76 impl->m_DataSeries->merge(dataSeries.get());
71
77 impl->m_DataSeries->unlock();
78 dataSeries->unlock();
72 79 emit updated();
73 80 }
74 81 }
@@ -3,6 +3,7
3 3 #include "Variable/Variable.h"
4 4 #include <unordered_map>
5 5
6 #include <QThread>
6 7 Q_LOGGING_CATEGORY(LOG_VariableCacheController, "VariableCacheController")
7 8
8 9 struct VariableCacheController::VariableCacheControllerPrivate {
@@ -32,6 +33,8 VariableCacheController::VariableCacheController(QObject *parent)
32 33 void VariableCacheController::addDateTime(std::shared_ptr<Variable> variable,
33 34 const SqpDateTime &dateTime)
34 35 {
36 qCDebug(LOG_VariableCacheController()) << "VariableCacheController::addDateTime"
37 << QThread::currentThread()->objectName();
35 38 if (variable) {
36 39 auto findVariableIte = impl->m_VariableToSqpDateTimeListMap.find(variable);
37 40 if (findVariableIte == impl->m_VariableToSqpDateTimeListMap.end()) {
@@ -81,6 +84,9 QVector<SqpDateTime>
81 84 VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable> variable,
82 85 const SqpDateTime &dateTime)
83 86 {
87 qCDebug(LOG_VariableCacheController())
88 << "VariableCacheController::provideNotInCacheDateTimeList"
89 << QThread::currentThread()->objectName();
84 90 auto notInCache = QVector<SqpDateTime>{};
85 91
86 92 // This algorithm is recursif. The idea is to localise the start time then the end time in the
@@ -101,6 +107,8 VariableCacheController::provideNotInCacheDateTimeList(std::shared_ptr<Variable>
101 107 QVector<SqpDateTime>
102 108 VariableCacheController::dateCacheList(std::shared_ptr<Variable> variable) const noexcept
103 109 {
110 qCDebug(LOG_VariableCacheController()) << "VariableCacheController::dateCacheList"
111 << QThread::currentThread()->objectName();
104 112 try {
105 113 return impl->m_VariableToSqpDateTimeListMap.at(variable);
106 114 }
@@ -152,6 +152,8 void VariableController::createVariable(const QString &name,
152 152
153 153 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
154 154 {
155 qCDebug(LOG_VariableController()) << "VariableController::onDateTimeOnSelection"
156 << QThread::currentThread()->objectName();
155 157 auto selectedRows = impl->m_VariableSelectionModel->selectedRows();
156 158
157 159 for (const auto &selectedRow : qAsConst(selectedRows)) {
@@ -166,6 +168,8 void VariableController::onDateTimeOnSelection(const SqpDateTime &dateTime)
166 168 void VariableController::onRequestDataLoading(std::shared_ptr<Variable> variable,
167 169 const SqpDateTime &dateTime)
168 170 {
171 qCDebug(LOG_VariableController()) << "VariableController::onRequestDataLoading"
172 << QThread::currentThread()->objectName();
169 173 // we want to load data of the variable for the dateTime.
170 174 // First we check if the cache contains some of them.
171 175 // For the other, we ask the provider to give them.
@@ -18,6 +18,14 public:
18 18 m_VariableController{std::make_unique<VariableController>()},
19 19 m_VisualizationController{std::make_unique<VisualizationController>()}
20 20 {
21 QThread::currentThread()->setObjectName("MainThread");
22 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
23 m_DataSourceControllerThread.setObjectName("DataSourceControllerThread");
24 m_VariableController->moveToThread(&m_VariableControllerThread);
25 m_VariableControllerThread.setObjectName("VariableControllerThread");
26 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
27 m_VisualizationControllerThread.setObjectName("VisualizationControllerThread");
28
21 29 // /////////////////////////////// //
22 30 // Connections between controllers //
23 31 // /////////////////////////////// //
@@ -34,9 +42,6 public:
34 42 m_VisualizationController.get(),
35 43 SIGNAL(variableAboutToBeDeleted(std::shared_ptr<Variable>)), Qt::DirectConnection);
36 44
37 m_DataSourceController->moveToThread(&m_DataSourceControllerThread);
38 m_VariableController->moveToThread(&m_VariableControllerThread);
39 m_VisualizationController->moveToThread(&m_VisualizationControllerThread);
40 45
41 46 // Additionnal init
42 47 m_VariableController->setTimeController(m_TimeController.get());
@@ -5,12 +5,16
5 5
6 6 #include <Variable/Variable.h>
7 7
8 #include <QElapsedTimer>
9
10 8 Q_LOGGING_CATEGORY(LOG_VisualizationGraphHelper, "VisualizationGraphHelper")
11 9
12 10 namespace {
13 11
12 class SqpDataContainer : public QCPGraphDataContainer {
13 public:
14 void appendGraphDataUnsorted(const QCPGraphData &data) { mData.append(data); }
15 };
16
17
14 18 /// Format for datetimes on a axis
15 19 const auto DATETIME_TICKER_FORMAT = QStringLiteral("yyyy/MM/dd \nhh:mm:ss");
16 20
@@ -33,35 +37,36 QSharedPointer<QCPAxisTicker> axisTicker(bool isTimeAxis)
33 37 void updateScalarData(QCPAbstractPlottable *component, ScalarSeries &scalarSeries,
34 38 const SqpDateTime &dateTime)
35 39 {
36 QElapsedTimer timer;
37 timer.start();
40 qCDebug(LOG_VisualizationGraphHelper()) << "TORM: updateScalarData"
41 << QThread::currentThread()->objectName();
38 42 if (auto qcpGraph = dynamic_cast<QCPGraph *>(component)) {
39 43 // Clean the graph
40 44 // NAIVE approch
41 const auto &xData = scalarSeries.xAxisData()->data();
42 const auto &valuesData = scalarSeries.valuesData()->data();
43 const auto count = xData.count();
44 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache" << xData.count();
45 auto xValue = QVector<double>(count);
46 auto vValue = QVector<double>(count);
47
48 int n = 0;
49 for (auto i = 0; i < count; ++i) {
50 const auto x = xData[i];
51 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
52 xValue[n] = x;
53 vValue[n] = valuesData[i];
54 ++n;
45 scalarSeries.lockRead();
46 {
47 const auto xData = scalarSeries.xAxisData()->data();
48 const auto valuesData = scalarSeries.valuesData()->data();
49 const auto count = xData.count();
50 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points in cache"
51 << xData.count();
52
53 auto dataContainer = qcpGraph->data();
54 dataContainer->clear();
55 auto sqpDataContainer = QSharedPointer<SqpDataContainer>::create();
56 qcpGraph->setData(sqpDataContainer);
57
58 for (auto i = 0; i < count; ++i) {
59 const auto x = xData[i];
60 if (x >= dateTime.m_TStart && x <= dateTime.m_TEnd) {
61 sqpDataContainer->appendGraphDataUnsorted(QCPGraphData(x, valuesData[i]));
62 }
55 63 }
64 sqpDataContainer->sort();
65 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
66 << sqpDataContainer->size();
56 67 }
68 scalarSeries.unlock();
57 69
58 xValue.resize(n);
59 vValue.resize(n);
60
61 qCInfo(LOG_VisualizationGraphHelper()) << "TORM: Current points displayed"
62 << xValue.count();
63
64 qcpGraph->setData(xValue, vValue);
65 70
66 71 // Display all data
67 72 component->rescaleAxes();
@@ -79,7 +79,6 void VisualizationGraphWidget::addVariable(std::shared_ptr<Variable> variable)
79 79
80 80 connect(variable.get(), SIGNAL(updated()), this, SLOT(onDataCacheVariableUpdated()));
81 81 }
82
83 82 void VisualizationGraphWidget::addVariableUsingGraph(std::shared_ptr<Variable> variable)
84 83 {
85 84
@@ -178,7 +177,8 void VisualizationGraphWidget::onGraphMenuRequested(const QPoint &pos) noexcept
178 177
179 178 void VisualizationGraphWidget::onRangeChanged(const QCPRange &t1)
180 179 {
181 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged");
180 qCDebug(LOG_VisualizationGraphWidget()) << tr("VisualizationGraphWidget::onRangeChanged")
181 << QThread::currentThread()->objectName();
182 182
183 183 for (auto it = impl->m_VariableToPlotMultiMap.cbegin();
184 184 it != impl->m_VariableToPlotMultiMap.cend(); ++it) {
@@ -18570,7 +18570,7 void QCPLegend::setIconSize(const QSize &size)
18570 18570 }
18571 18571
18572 18572 /*! \overload
18573 */
18573 */
18574 18574 void QCPLegend::setIconSize(int width, int height)
18575 18575 {
18576 18576 mIconSize.setWidth(width);
@@ -6,6 +6,7
6 6 #include <cmath>
7 7
8 8 #include <QDateTime>
9 #include <QThread>
9 10
10 11 Q_LOGGING_CATEGORY(LOG_CosinusProvider, "CosinusProvider")
11 12
@@ -39,6 +40,8 CosinusProvider::retrieveData(const DataProviderParameters &parameters) const
39 40
40 41 void CosinusProvider::requestDataLoading(const QVector<SqpDateTime> &dateTimeList)
41 42 {
43 qCDebug(LOG_CosinusProvider()) << "CosinusProvider::requestDataLoading"
44 << QThread::currentThread()->objectName();
42 45 // NOTE: Try to use multithread if possible
43 46 for (const auto &dateTime : dateTimeList) {
44 47 auto scalarSeries = this->retrieveData(DataProviderParameters{dateTime});
General Comments 0
You need to be logged in to leave comments. Login now