From f4eadddee751ca9c5b070c00ebd0ca345f135242 Mon Sep 17 00:00:00 2001 From: Mathew Sutcliffe Date: Wed, 27 Apr 2016 19:39:49 +0100 Subject: [PATCH] refs #644 Add method CCached::save, like setAndSave but using the currently set value. Implemented with a flag in CValueCachePacket to indicate a request to save only. --- src/blackmisc/datacache.h | 3 +++ src/blackmisc/valuecache.cpp | 36 ++++++++++++++++++++++--------- src/blackmisc/valuecache.h | 14 +++++++++--- src/blackmisc/valuecacheprivate.h | 2 +- 4 files changed, 41 insertions(+), 14 deletions(-) diff --git a/src/blackmisc/datacache.h b/src/blackmisc/datacache.h index b910717c8..2d6ae27e0 100644 --- a/src/blackmisc/datacache.h +++ b/src/blackmisc/datacache.h @@ -268,6 +268,9 @@ namespace BlackMisc //! Data cache doesn't support setAndSave (because set() already causes save anyway). CStatusMessage setAndSave(const typename Trait::type &value, qint64 timestamp = 0) = delete; + + //! Data cache doesn't support save (because currently set value is saved already). + CStatusMessage save() = delete; }; /*! diff --git a/src/blackmisc/valuecache.cpp b/src/blackmisc/valuecache.cpp index 19095388c..a31db89cb 100644 --- a/src/blackmisc/valuecache.cpp +++ b/src/blackmisc/valuecache.cpp @@ -33,8 +33,8 @@ namespace BlackMisc // CValueCachePacket //////////////////////////////// - CValueCachePacket::CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved) : - m_saved(saved) + CValueCachePacket::CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved, bool valuesChanged) : + m_saved(saved), m_valuesChanged(valuesChanged) { for (auto it = values.cbegin(); it != values.cend(); ++it) { @@ -182,13 +182,16 @@ namespace BlackMisc while (out != end && out.key() < in.key()) { ++out; } auto &element = getElement(in.key(), out); - Q_ASSERT(isSafeToIncrement(element.m_pendingChanges)); - element.m_pendingChanges++; - element.m_value = in.value(); - element.m_timestamp = in.timestamp(); + if (values.valuesChanged()) + { + Q_ASSERT(isSafeToIncrement(element.m_pendingChanges)); + element.m_pendingChanges++; + element.m_value = in.value(); + element.m_timestamp = in.timestamp(); + } element.m_saved = values.isSaved(); } - emit valuesChanged(values, sender()); + if (values.valuesChanged()) { emit valuesChanged(values, sender()); } emit valuesChangedByLocal(values); } @@ -196,6 +199,11 @@ namespace BlackMisc { QMutexLocker lock(&m_mutex); if (values.empty()) { return; } + if (! values.valuesChanged()) + { + if (values.isSaved()) { emit valuesSaveRequested(values); } + return; + } CValueCachePacket ratifiedChanges(values.isSaved()); auto out = m_elements.lowerBound(values.cbegin().key()); auto end = m_elements.upperBound((values.cend() - 1).key()); @@ -453,17 +461,24 @@ namespace BlackMisc return element.m_value.read(); } - CStatusMessage CValuePage::setValue(Element &element, const CVariant &value, qint64 timestamp, bool save) + CStatusMessage CValuePage::setValue(Element &element, CVariant value, qint64 timestamp, bool save, bool ignoreValue) { Q_ASSERT(QThread::currentThread() == thread()); if (timestamp == 0) { timestamp = QDateTime::currentMSecsSinceEpoch(); } - if (element.m_value.read() == value && element.m_timestamp == timestamp) { return {}; } + if (element.m_value.read() == value && element.m_timestamp == timestamp && ! ignoreValue) { return {}; } + + if (ignoreValue) { value = element.m_value.read(); } auto status = validate(element, value, CStatusMessage::SeverityError); if (status.isSuccess()) { - if (m_batchMode > 0) + if (ignoreValue) + { + element.m_saved = save; + emit valuesWantToCache({ { { element.m_key, {} } }, 0, save, false }); + } + else if (m_batchMode > 0) { m_batchedValues[element.m_key] = value; } @@ -505,6 +520,7 @@ namespace BlackMisc void CValuePage::setValuesFromCache(const CValueCachePacket &values, QObject *changedBy) { Q_ASSERT(QThread::currentThread() == thread()); + Q_ASSERT_X(values.valuesChanged(), Q_FUNC_INFO, "packet with unchanged values should not reach here"); QList notifySlots; diff --git a/src/blackmisc/valuecache.h b/src/blackmisc/valuecache.h index f7e350c71..034865b8d 100644 --- a/src/blackmisc/valuecache.h +++ b/src/blackmisc/valuecache.h @@ -35,10 +35,13 @@ namespace BlackMisc using base_type = CDictionary; //! Constructor. - CValueCachePacket(bool saved = false) : m_saved(saved) {} + CValueCachePacket(bool saved = false, bool valuesChanged = true) : m_saved(saved), m_valuesChanged(valuesChanged) {} //! Construct from CVariantMap and a timestamp. - CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved = false); + CValueCachePacket(const CVariantMap &values, qint64 timestamp, bool saved = false, bool valuesChanged = true); + + //! Values have been changed. + bool valuesChanged() const { return m_valuesChanged; } //! Values are to be saved. //! @{ @@ -90,10 +93,12 @@ namespace BlackMisc private: bool m_saved = false; + bool m_valuesChanged = true; BLACK_METACLASS( CValueCachePacket, - BLACK_METAMEMBER(saved) + BLACK_METAMEMBER(saved), + BLACK_METAMEMBER(valuesChanged) ); }; @@ -304,6 +309,9 @@ namespace BlackMisc //! Write and save in the same step. Must be called from the thread in which the owner lives. CStatusMessage setAndSave(const T &value, qint64 timestamp = 0) { return m_page.setValue(m_element, CVariant::from(value), timestamp, true); } + //! Save using the currently set value. Must be called from the thread in which the owner lives. + CStatusMessage save() { return m_page.setValue(m_element, {}, 0, true, true); } + //! Is current thread the owner thread, so CCached::set is safe bool isOwnerThread() const { return QThread::currentThread() == m_page.thread(); } diff --git a/src/blackmisc/valuecacheprivate.h b/src/blackmisc/valuecacheprivate.h index 918896435..56a0bb884 100644 --- a/src/blackmisc/valuecacheprivate.h +++ b/src/blackmisc/valuecacheprivate.h @@ -69,7 +69,7 @@ namespace BlackMisc CVariant getValueCopy(const Element &element) const; //! Write the value corresponding to the element's key and begin synchronizing it to any other pages. - CStatusMessage setValue(Element &element, const CVariant &value, qint64 timestamp, bool save = false); + CStatusMessage setValue(Element &element, CVariant value, qint64 timestamp, bool save = false, bool ignoreValue = false); //! Get the key string corresponding to the element. const QString &getKey(const Element &element) const;