mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-17 10:55:32 +08:00
refs #659 Use a threadsafe queue for admit(), to avoid a race with synchronize().
This commit is contained in:
@@ -147,7 +147,7 @@ namespace BlackMisc
|
|||||||
|
|
||||||
void CDataCache::admitValue(const QString &key, bool triggerLoad)
|
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(); }
|
if (triggerLoad) { loadFromStoreAsync(); }
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -331,7 +331,7 @@ namespace BlackMisc
|
|||||||
if (json.contains("uuid") && json.contains("timestamps"))
|
if (json.contains("uuid") && json.contains("timestamps"))
|
||||||
{
|
{
|
||||||
QUuid uuid(json.value("uuid").toString());
|
QUuid uuid(json.value("uuid").toString());
|
||||||
if (uuid == m_uuid)
|
if (uuid == m_uuid && m_admittedQueue.isEmpty())
|
||||||
{
|
{
|
||||||
if (m_pendingWrite) { return guard; }
|
if (m_pendingWrite) { return guard; }
|
||||||
return {};
|
return {};
|
||||||
@@ -365,6 +365,8 @@ namespace BlackMisc
|
|||||||
}
|
}
|
||||||
|
|
||||||
auto deferrals = fromJson(json.value("deferrals").toArray());
|
auto deferrals = fromJson(json.value("deferrals").toArray());
|
||||||
|
m_admittedValues.unite(m_admittedQueue);
|
||||||
|
if (updateUuid) { m_admittedQueue.clear(); }
|
||||||
for (const auto &key : m_timestamps.keys())
|
for (const auto &key : m_timestamps.keys())
|
||||||
{
|
{
|
||||||
if (deferrals.contains(key) && ! m_admittedValues.contains(key)) { m_timestamps.remove(key); }
|
if (deferrals.contains(key) && ! m_admittedValues.contains(key)) { m_timestamps.remove(key); }
|
||||||
@@ -463,7 +465,10 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
QMutexLocker lock(&m_mutex);
|
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)
|
std::future<void> CDataCacheRevision::promiseLoadedValue(const QString &key, qint64 currentTimestamp)
|
||||||
@@ -569,9 +574,9 @@ namespace BlackMisc
|
|||||||
|
|
||||||
void CDataCacheRevision::admitValue(const QString &key)
|
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> ×tamps)
|
QJsonObject CDataCacheRevision::toJson(const QMap<QString, qint64> ×tamps)
|
||||||
|
|||||||
@@ -163,6 +163,7 @@ namespace BlackMisc
|
|||||||
QSet<QString> m_pinnedValues;
|
QSet<QString> m_pinnedValues;
|
||||||
QSet<QString> m_deferredValues;
|
QSet<QString> m_deferredValues;
|
||||||
QSet<QString> m_admittedValues;
|
QSet<QString> m_admittedValues;
|
||||||
|
QSet<QString> m_admittedQueue;
|
||||||
std::vector<std::promise<void>> m_promises;
|
std::vector<std::promise<void>> m_promises;
|
||||||
|
|
||||||
static QJsonObject toJson(const QMap<QString, qint64> ×tamps);
|
static QJsonObject toJson(const QMap<QString, qint64> ×tamps);
|
||||||
@@ -311,7 +312,7 @@ namespace BlackMisc
|
|||||||
void renewTimestamp(qint64 timestamp) { return CDataCache::instance()->renewTimestamp(this->getKey(), timestamp); }
|
void renewTimestamp(qint64 timestamp) { return CDataCache::instance()->renewTimestamp(this->getKey(), timestamp); }
|
||||||
|
|
||||||
//! If the value is load-deferred, trigger the deferred load (async).
|
//! 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.
|
//! If the value is currently being loaded, wait for it to finish loading, and call the notification slot, if any.
|
||||||
void synchronize()
|
void synchronize()
|
||||||
|
|||||||
Reference in New Issue
Block a user