refs #659 Use a threadsafe queue for admit(), to avoid a race with synchronize().

This commit is contained in:
Mathew Sutcliffe
2016-05-29 14:21:29 +01:00
parent f1a9ae5a13
commit 5559d1fcc6
2 changed files with 12 additions and 6 deletions

View File

@@ -147,7 +147,7 @@ namespace BlackMisc
void CDataCache::admitValue(const QString &key, bool triggerLoad)
{
QTimer::singleShot(0, &m_serializer, [this, key] { m_revision.admitValue(key); });
m_revision.admitValue(key);
if (triggerLoad) { loadFromStoreAsync(); }
}
@@ -331,7 +331,7 @@ namespace BlackMisc
if (json.contains("uuid") && json.contains("timestamps"))
{
QUuid uuid(json.value("uuid").toString());
if (uuid == m_uuid)
if (uuid == m_uuid && m_admittedQueue.isEmpty())
{
if (m_pendingWrite) { return guard; }
return {};
@@ -365,6 +365,8 @@ namespace BlackMisc
}
auto deferrals = fromJson(json.value("deferrals").toArray());
m_admittedValues.unite(m_admittedQueue);
if (updateUuid) { m_admittedQueue.clear(); }
for (const auto &key : m_timestamps.keys())
{
if (deferrals.contains(key) && ! m_admittedValues.contains(key)) { m_timestamps.remove(key); }
@@ -463,7 +465,10 @@ namespace BlackMisc
{
QMutexLocker lock(&m_mutex);
return (m_updateInProgress || m_pendingWrite || beginUpdate({{ key, timestamp }}, false)) && m_timestamps.contains(key);
// Temporary guard object returned by beginUpdate is deleted at the end of the full expression,
// don't try to split the conditional into multiple statements.
return (m_updateInProgress || m_pendingWrite || beginUpdate({{ key, timestamp }}, false))
&& (m_timestamps.contains(key) || m_admittedQueue.contains(key));
}
std::future<void> CDataCacheRevision::promiseLoadedValue(const QString &key, qint64 currentTimestamp)
@@ -569,9 +574,9 @@ namespace BlackMisc
void CDataCacheRevision::admitValue(const QString &key)
{
Q_ASSERT(! m_updateInProgress);
QMutexLocker lock(&m_mutex);
m_admittedValues.insert(key);
m_admittedQueue.insert(key);
}
QJsonObject CDataCacheRevision::toJson(const QMap<QString, qint64> &timestamps)

View File

@@ -163,6 +163,7 @@ namespace BlackMisc
QSet<QString> m_pinnedValues;
QSet<QString> m_deferredValues;
QSet<QString> m_admittedValues;
QSet<QString> m_admittedQueue;
std::vector<std::promise<void>> m_promises;
static QJsonObject toJson(const QMap<QString, qint64> &timestamps);
@@ -311,7 +312,7 @@ namespace BlackMisc
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); }
void admit() { if (Trait::isDeferred()) { 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()