diff --git a/include/Data/DataSeries.h b/include/Data/DataSeries.h index 352896d..8bdabac 100644 --- a/include/Data/DataSeries.h +++ b/include/Data/DataSeries.h @@ -207,7 +207,7 @@ class SCIQLOP_CORE_EXPORT DataSeries : public IDataSeries { public: /// @sa IDataSeries::xAxisData() std::shared_ptr > xAxisData() override { return m_XAxisData; } - const std::shared_ptr > xAxisData() const { return m_XAxisData; } + const std::shared_ptr > xAxisData() const override { return m_XAxisData; } /// @sa IDataSeries::xAxisUnit() Unit xAxisUnit() const override { return m_XAxisUnit; } @@ -415,9 +415,12 @@ public: // Mutexes // // /////// // - virtual void lockRead() { m_Lock.lockForRead(); } - virtual void lockWrite() { m_Lock.lockForWrite(); } - virtual void unlock() { m_Lock.unlock(); } + virtual QReadLocker getReadLock() override { return QReadLocker{&m_Lock}; } + virtual QWriteLocker getWriteLock() override { return QWriteLocker{&m_Lock}; } + + virtual void lockRead() override { m_Lock.lockForRead(); } + virtual void lockWrite() override { m_Lock.lockForWrite(); } + virtual void unlock() override { m_Lock.unlock(); } protected: /// Protected ctor (DataSeries is abstract). diff --git a/include/Data/IDataSeries.h b/include/Data/IDataSeries.h index 58aa674..a5f6b35 100644 --- a/include/Data/IDataSeries.h +++ b/include/Data/IDataSeries.h @@ -1,14 +1,17 @@ #ifndef SCIQLOP_IDATASERIES_H #define SCIQLOP_IDATASERIES_H +#include + +#include +#include + #include #include #include #include +#include -#include - -#include template class ArrayData; @@ -90,10 +93,13 @@ public: // /////// // // Mutexes // // /////// // - + virtual QReadLocker getReadLock() = 0; + virtual QWriteLocker getWriteLock() = 0; +DEPRECATE( virtual void lockRead() = 0; virtual void lockWrite() = 0; virtual void unlock() = 0; + ) }; // Required for using shared_ptr in signals/slots diff --git a/include/Data/VectorSeries.h b/include/Data/VectorSeries.h index 5d39a81..9dcd780 100644 --- a/include/Data/VectorSeries.h +++ b/include/Data/VectorSeries.h @@ -26,7 +26,7 @@ public: explicit VectorSeries(std::vector xAxisData, std::vector valuesData, const Unit &xAxisUnit, const Unit &valuesUnit); - std::unique_ptr clone() const; + std::unique_ptr clone() const override; std::shared_ptr subDataSeries(const DateTimeRange &range) override; }; diff --git a/include/Variable/Variable.h b/include/Variable/Variable.h index baaa6e1..228bef7 100644 --- a/include/Variable/Variable.h +++ b/include/Variable/Variable.h @@ -1,15 +1,16 @@ #ifndef SCIQLOP_VARIABLE_H #define SCIQLOP_VARIABLE_H -#include "CoreGlobal.h" +#include +#include +#include +#include +#include "CoreGlobal.h" #include #include #include -#include -#include -#include #include #include @@ -77,7 +78,10 @@ DEPRECATE( DEPRECATE( void mergeDataSeries(std::shared_ptr dataSeries) noexcept; ) - void mergeDataSeries(IDataSeries* dataSeries, bool notify=false) noexcept; + + void updateData(const std::vector& dataSeries, + const DateTimeRange& newRange, const DateTimeRange& newCacheRange, + bool notify=true); DEPRECATE( static QVector provideNotInCacheRangeList(const DateTimeRange &oldRange, @@ -98,6 +102,7 @@ private: class VariablePrivate; spimpl::unique_impl_ptr impl; QUuid _uuid; + QReadWriteLock m_lock; }; // Required for using shared_ptr in signals/slots diff --git a/src/Variable/Variable.cpp b/src/Variable/Variable.cpp index 7e4b4d3..a09a586 100644 --- a/src/Variable/Variable.cpp +++ b/src/Variable/Variable.cpp @@ -12,7 +12,6 @@ Q_LOGGING_CATEGORY(LOG_Variable, "Variable") -namespace { /** * Searches in metadata for a value that can be converted to DataSeriesType @@ -20,7 +19,7 @@ namespace { * @return the value converted to a DataSeriesType if it was found, UNKNOWN type otherwise * @sa DataSeriesType */ -DataSeriesType findDataSeriesType(const QVariantHash &metadata) +static DataSeriesType findDataSeriesType(const QVariantHash &metadata) { auto dataSeriesType = DataSeriesType::UNKNOWN; @@ -33,7 +32,6 @@ DataSeriesType findDataSeriesType(const QVariantHash &metadata) return dataSeriesType; } -} // namespace #define VP_PROPERTY(property,getter,setter,type) \ type getter() noexcept\ @@ -95,23 +93,31 @@ struct Variable::VariablePrivate { updateRealRange(); updateNbPoints(); } - + void mergeDataSeries(const std::vector& dataseries) + { + QWriteLocker lock{&m_Lock}; + for(auto ds:dataseries) + { + if(m_DataSeries) + m_DataSeries->merge(ds); + else + m_DataSeries = ds->clone(); + } + } void updateNbPoints() { m_NbPoints = m_DataSeries ? m_DataSeries->nbPoints() : 0; } /// Updates real range according to current variable range and data series void updateRealRange() { if (m_DataSeries) { - m_DataSeries->lockRead(); + auto lock = m_DataSeries->getReadLock(); auto end = m_DataSeries->cend(); auto minXAxisIt = m_DataSeries->minXAxisData(m_Range.m_TStart); auto maxXAxisIt = m_DataSeries->maxXAxisData(m_Range.m_TEnd); - - m_RealRange - = (minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x()) - ? DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()} - : INVALID_RANGE; - m_DataSeries->unlock(); + if(minXAxisIt != end && maxXAxisIt != end && minXAxisIt->x() <= maxXAxisIt->x()) + m_RealRange = DateTimeRange{minXAxisIt->x(), maxXAxisIt->x()}; + else + m_RealRange = std::nullopt; } else { m_RealRange = std::nullopt; @@ -201,34 +207,17 @@ void Variable::mergeDataSeries(std::shared_ptr dataSeries) noexcept } } -void Variable::mergeDataSeries(IDataSeries *dataSeries, bool notify) noexcept +void Variable::updateData(const std::vector &dataSeries, const DateTimeRange &newRange, const DateTimeRange &newCacheRange, bool notify) { - if (dataSeries==nullptr) { - SCIQLOP_ERROR(Variable,"Given IDataSeries is nullptr"); - return; - } - - auto dataInit = false; - // @TODO move impl to Pimpl this is what it stands for... - // Add or merge the data - impl->lockWrite(); - if (!impl->m_DataSeries) { - //@TODO find a better way - impl->m_DataSeries = dataSeries->clone(); - dataInit = true; - delete dataSeries; - } - else { - impl->m_DataSeries->merge(dataSeries); - } - impl->purgeDataSeries(); - impl->unlock(); - - if (dataInit) { - emit dataInitialized(); + { + QWriteLocker lock{&m_lock}; + impl->mergeDataSeries(dataSeries); + impl->setRange(newRange); + impl->setCacheRange(newCacheRange); + impl->purgeDataSeries(); } if(notify) - emit this->updated(); + emit updated(); } diff --git a/src/Variable/VariableController2.cpp b/src/Variable/VariableController2.cpp index ab5a1ac..1e47a27 100644 --- a/src/Variable/VariableController2.cpp +++ b/src/Variable/VariableController2.cpp @@ -40,13 +40,12 @@ class VariableController2::VariableController2Private newCacheRange = _cacheStrategy->computeRange(var->cacheRange(),r); missingRanges = newCacheRange - var->cacheRange(); } + std::vector data; for(auto range:missingRanges) { - auto data = provider->getData(DataProviderParameters{{range},var->metadata()}); - var->mergeDataSeries(data); + data.push_back(provider->getData(DataProviderParameters{{range},var->metadata()})); } - var->setCacheRange(newCacheRange); - var->setRange(r); + var->updateData(data,r,newCacheRange,true); } public: VariableController2Private(QObject* parent=Q_NULLPTR) diff --git a/tests/Variable/TestVariableController.cpp b/tests/Variable/TestVariableController.cpp index 04f9351..ab21b4e 100644 --- a/tests/Variable/TestVariableController.cpp +++ b/tests/Variable/TestVariableController.cpp @@ -12,7 +12,7 @@ namespace { /// Provider used for the tests class TestProvider : public IDataProvider { - std::shared_ptr clone() const { return std::make_shared(); } + std::shared_ptr clone() const override { return std::make_shared(); } void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters ¶meters) override { diff --git a/tests/Variable/TestVariableSync.cpp b/tests/Variable/TestVariableSync.cpp index 9fad214..7a22f2a 100644 --- a/tests/Variable/TestVariableSync.cpp +++ b/tests/Variable/TestVariableSync.cpp @@ -69,7 +69,7 @@ void validateRanges(VariableController &variableController, /// Provider used for the tests class TestProvider : public IDataProvider { - std::shared_ptr clone() const { return std::make_shared(); } + std::shared_ptr clone() const override { return std::make_shared(); } void requestDataLoading(QUuid acqIdentifier, const DataProviderParameters ¶meters) override {