diff --git a/src/blackmisc/valuecache.cpp b/src/blackmisc/valuecache.cpp index 4ea757c54..f72ad6318 100644 --- a/src/blackmisc/valuecache.cpp +++ b/src/blackmisc/valuecache.cpp @@ -11,6 +11,7 @@ #include "blackmisc/identifier.h" #include "blackmisc/logmessage.h" #include "blackmisc/algorithm.h" +#include "blackmisc/lockfree.h" #include #include @@ -270,7 +271,7 @@ namespace BlackMisc m_key(key), m_metaType(metaType), m_validator(validator), m_default(defaultValue), m_notifySlot(slot) {} const QString m_key; - CVariant m_value; + LockFree m_value; const int m_metaType = QMetaType::UnknownType; const Validator m_validator; const CVariant m_default; @@ -285,29 +286,27 @@ namespace BlackMisc Q_ASSERT_X(defaultValue.isValid() && validator ? validator(defaultValue) : true, "CValuePage", "Validator rejects default value"); auto &element = *(m_elements[key] = ElementPtr(new Element(key, metaType, validator, defaultValue, slot))); - element.m_value = m_cache->getValue(key); + element.m_value.uniqueWrite() = m_cache->getValue(key); - auto error = validate(element, element.m_value); + auto error = validate(element, element.m_value.read()); if (! error.isEmpty()) { CLogMessage::preformatted(error); - element.m_value = defaultValue; + element.m_value.uniqueWrite() = defaultValue; } return element; } const CVariant &CValuePage::getValue(const Element &element) const { - Q_ASSERT(QThread::currentThread() == thread()); - - return element.m_value; + return element.m_value.read(); } CStatusMessage CValuePage::setValue(Element &element, const CVariant &value) { Q_ASSERT(QThread::currentThread() == thread()); - if (element.m_value == value) { return {}; } + if (element.m_value.read() == value) { return {}; } auto error = validate(element, value); if (error.isEmpty()) @@ -321,7 +320,7 @@ namespace BlackMisc Q_ASSERT(isSafeToIncrement(element.m_pendingChanges)); element.m_pendingChanges++; - element.m_value = value; + element.m_value.uniqueWrite() = value; emit valuesWantToCache({ { element.m_key, value } }); } } @@ -351,7 +350,7 @@ namespace BlackMisc auto error = validate(*element, value); if (error.isEmpty()) { - element->m_value = value; + element->m_value.uniqueWrite() = value; if (element->m_notifySlot && ! notifySlots.contains(element->m_notifySlot)) { notifySlots.push_back(element->m_notifySlot); } } else @@ -394,7 +393,7 @@ namespace BlackMisc { Q_ASSERT(isSafeToIncrement(element->m_pendingChanges)); element->m_pendingChanges++; - element->m_value = value; + element->m_value.uniqueWrite() = value; }); emit valuesWantToCache(m_batchedValues); } diff --git a/src/blackmisc/valuecache.h b/src/blackmisc/valuecache.h index 3f249e5b7..f081ba41f 100644 --- a/src/blackmisc/valuecache.h +++ b/src/blackmisc/valuecache.h @@ -156,7 +156,8 @@ namespace BlackMisc m_element(m_page.createElement(key, qMetaTypeId(), wrap(validator), CVariant::from(defaultValue), slot_cast(slot))) {} - //! Read the current value. Must be called from the thread in which the owner lives. + //! Read the current value. + //! \threadsafe const T &get() const { static const T empty {}; return *(isValid() ? static_cast(getVariant().data()) : &empty); } //! Write a new value. Must be called from the thread in which the owner lives. diff --git a/src/blackmisc/valuecache_private.h b/src/blackmisc/valuecache_private.h index c5fd5cb71..86ce2923c 100644 --- a/src/blackmisc/valuecache_private.h +++ b/src/blackmisc/valuecache_private.h @@ -57,6 +57,7 @@ namespace BlackMisc Element &createElement(const QString &key, int metaType, Validator validator, const CVariant &defaultValue, NotifySlot slot); //! Read the currently paged value corresponding to the element's key. + //! \threadsafe const CVariant &getValue(const Element &element) const; //! Write the value corresponding to the element's key and begin synchronizing it to any other pages.