diff --git a/src/blackmisc/datacache.cpp b/src/blackmisc/datacache.cpp index 3d06c4398..9d9369c22 100644 --- a/src/blackmisc/datacache.cpp +++ b/src/blackmisc/datacache.cpp @@ -145,6 +145,12 @@ namespace BlackMisc QTimer::singleShot(0, &m_serializer, [this, key] { m_revision.deferValue(key); }); } + void CDataCache::admitValue(const QString &key, bool triggerLoad) + { + QTimer::singleShot(0, &m_serializer, [this, key] { m_revision.admitValue(key); }); + if (triggerLoad) { loadFromStoreAsync(); } + } + QString lockFileError(const QLockFile &lock) { switch (lock.error()) @@ -361,7 +367,7 @@ namespace BlackMisc auto deferrals = fromJson(json.value("deferrals").toArray()); for (const auto &key : m_timestamps.keys()) { - if (deferrals.contains(key)) { m_timestamps.remove(key); } + if (deferrals.contains(key) && ! m_admittedValues.contains(key)) { m_timestamps.remove(key); } } } else if (revisionFile.size() > 0) @@ -561,6 +567,13 @@ namespace BlackMisc m_deferredValues.insert(key); } + void CDataCacheRevision::admitValue(const QString &key) + { + Q_ASSERT(! m_updateInProgress); + + m_admittedValues.insert(key); + } + QJsonObject CDataCacheRevision::toJson(const QMap ×tamps) { QJsonObject result; diff --git a/src/blackmisc/datacache.h b/src/blackmisc/datacache.h index 6f84456f7..c03a44df5 100644 --- a/src/blackmisc/datacache.h +++ b/src/blackmisc/datacache.h @@ -147,6 +147,9 @@ namespace BlackMisc //! Set the flag which will cause the value to be deferred-loaded. void deferValue(const QString &key); + //! Set the flag which will cause a deferred-load value to be loaded. + void admitValue(const QString &key); + private: mutable QMutex m_mutex { QMutex::Recursive }; bool m_updateInProgress = false; @@ -159,6 +162,7 @@ namespace BlackMisc QMap m_timesToLive; QSet m_pinnedValues; QSet m_deferredValues; + QSet m_admittedValues; std::vector> m_promises; static QJsonObject toJson(const QMap ×tamps); @@ -242,6 +246,9 @@ namespace BlackMisc //! Method used for implementing deferring values. void deferValue(const QString &key); + //! Method used for implementing deferring values. + void admitValue(const QString &key, bool triggerLoad); + private: CDataCache(); @@ -284,6 +291,13 @@ namespace BlackMisc static_assert(! (Trait::isPinned() && Trait::isDeferred()), "trait can not be both pinned and deferred"); } + //! \copydoc BlackMisc::CCached::set + CStatusMessage set(const typename Trait::type &value, qint64 timestamp = 0) + { + CDataCache::instance()->admitValue(Trait::key(), false); + return CCached::set(value, timestamp); + } + //! Reset the data to its default value. void setDefault() { this->set(Trait::defaultValue()); } @@ -296,12 +310,17 @@ namespace BlackMisc //! Don't change the value, but write a new timestamp, to extend the life of the value. void renewTimestamp(qint64 timestamp) { return CDataCache::instance()->renewTimestamp(this->getKey(), timestamp); } + //! If the value is load-deferred, trigger the deferred load (async). + void admit() { CDataCache::instance()->admitValue(Trait::key(), true); } + //! If the value is currently being loaded, wait for it to finish loading, and call the notification slot, if any. void synchronize() { auto *queue = this->m_page.template findChild(); Q_ASSERT(queue); + admit(); CDataCache::instance()->synchronize(this->getKey()); + CDataCache::instance()->synchronize(this->getKey()); // if load was in progress when admit() was called, synchronize with the next load queue->setQueuedValueFromCache(this->getKey()); }