mirror of
https://github.com/swift-project/pilotclient.git
synced 2026-04-20 04:25:42 +08:00
refs #495 Using LockFree to make CCached::get() threadsafe.
This commit is contained in:
@@ -11,6 +11,7 @@
|
|||||||
#include "blackmisc/identifier.h"
|
#include "blackmisc/identifier.h"
|
||||||
#include "blackmisc/logmessage.h"
|
#include "blackmisc/logmessage.h"
|
||||||
#include "blackmisc/algorithm.h"
|
#include "blackmisc/algorithm.h"
|
||||||
|
#include "blackmisc/lockfree.h"
|
||||||
#include <QThread>
|
#include <QThread>
|
||||||
#include <QJsonDocument>
|
#include <QJsonDocument>
|
||||||
|
|
||||||
@@ -270,7 +271,7 @@ namespace BlackMisc
|
|||||||
m_key(key), m_metaType(metaType), m_validator(validator), m_default(defaultValue), m_notifySlot(slot)
|
m_key(key), m_metaType(metaType), m_validator(validator), m_default(defaultValue), m_notifySlot(slot)
|
||||||
{}
|
{}
|
||||||
const QString m_key;
|
const QString m_key;
|
||||||
CVariant m_value;
|
LockFree<CVariant> m_value;
|
||||||
const int m_metaType = QMetaType::UnknownType;
|
const int m_metaType = QMetaType::UnknownType;
|
||||||
const Validator m_validator;
|
const Validator m_validator;
|
||||||
const CVariant m_default;
|
const CVariant m_default;
|
||||||
@@ -285,29 +286,27 @@ namespace BlackMisc
|
|||||||
Q_ASSERT_X(defaultValue.isValid() && validator ? validator(defaultValue) : true, "CValuePage", "Validator rejects default value");
|
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)));
|
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())
|
if (! error.isEmpty())
|
||||||
{
|
{
|
||||||
CLogMessage::preformatted(error);
|
CLogMessage::preformatted(error);
|
||||||
element.m_value = defaultValue;
|
element.m_value.uniqueWrite() = defaultValue;
|
||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
const CVariant &CValuePage::getValue(const Element &element) const
|
const CVariant &CValuePage::getValue(const Element &element) const
|
||||||
{
|
{
|
||||||
Q_ASSERT(QThread::currentThread() == thread());
|
return element.m_value.read();
|
||||||
|
|
||||||
return element.m_value;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CStatusMessage CValuePage::setValue(Element &element, const CVariant &value)
|
CStatusMessage CValuePage::setValue(Element &element, const CVariant &value)
|
||||||
{
|
{
|
||||||
Q_ASSERT(QThread::currentThread() == thread());
|
Q_ASSERT(QThread::currentThread() == thread());
|
||||||
|
|
||||||
if (element.m_value == value) { return {}; }
|
if (element.m_value.read() == value) { return {}; }
|
||||||
|
|
||||||
auto error = validate(element, value);
|
auto error = validate(element, value);
|
||||||
if (error.isEmpty())
|
if (error.isEmpty())
|
||||||
@@ -321,7 +320,7 @@ namespace BlackMisc
|
|||||||
Q_ASSERT(isSafeToIncrement(element.m_pendingChanges));
|
Q_ASSERT(isSafeToIncrement(element.m_pendingChanges));
|
||||||
element.m_pendingChanges++;
|
element.m_pendingChanges++;
|
||||||
|
|
||||||
element.m_value = value;
|
element.m_value.uniqueWrite() = value;
|
||||||
emit valuesWantToCache({ { element.m_key, value } });
|
emit valuesWantToCache({ { element.m_key, value } });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -351,7 +350,7 @@ namespace BlackMisc
|
|||||||
auto error = validate(*element, value);
|
auto error = validate(*element, value);
|
||||||
if (error.isEmpty())
|
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); }
|
if (element->m_notifySlot && ! notifySlots.contains(element->m_notifySlot)) { notifySlots.push_back(element->m_notifySlot); }
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -394,7 +393,7 @@ namespace BlackMisc
|
|||||||
{
|
{
|
||||||
Q_ASSERT(isSafeToIncrement(element->m_pendingChanges));
|
Q_ASSERT(isSafeToIncrement(element->m_pendingChanges));
|
||||||
element->m_pendingChanges++;
|
element->m_pendingChanges++;
|
||||||
element->m_value = value;
|
element->m_value.uniqueWrite() = value;
|
||||||
});
|
});
|
||||||
emit valuesWantToCache(m_batchedValues);
|
emit valuesWantToCache(m_batchedValues);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -156,7 +156,8 @@ namespace BlackMisc
|
|||||||
m_element(m_page.createElement(key, qMetaTypeId<T>(), wrap(validator), CVariant::from(defaultValue), slot_cast(slot)))
|
m_element(m_page.createElement(key, qMetaTypeId<T>(), 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<const T *>(getVariant().data()) : &empty); }
|
const T &get() const { static const T empty {}; return *(isValid() ? static_cast<const T *>(getVariant().data()) : &empty); }
|
||||||
|
|
||||||
//! Write a new value. Must be called from the thread in which the owner lives.
|
//! Write a new value. Must be called from the thread in which the owner lives.
|
||||||
|
|||||||
@@ -57,6 +57,7 @@ namespace BlackMisc
|
|||||||
Element &createElement(const QString &key, int metaType, Validator validator, const CVariant &defaultValue, NotifySlot slot);
|
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.
|
//! Read the currently paged value corresponding to the element's key.
|
||||||
|
//! \threadsafe
|
||||||
const CVariant &getValue(const Element &element) const;
|
const CVariant &getValue(const Element &element) const;
|
||||||
|
|
||||||
//! Write the value corresponding to the element's key and begin synchronizing it to any other pages.
|
//! Write the value corresponding to the element's key and begin synchronizing it to any other pages.
|
||||||
|
|||||||
Reference in New Issue
Block a user