refs #601 CDataCache overrides connectPage to provide a queue that is more flexible than the usual Qt::QueuedConnection.

This commit is contained in:
Mathew Sutcliffe
2016-03-09 20:46:39 +00:00
parent 899d94ca74
commit 06ad77ee9d
3 changed files with 69 additions and 1 deletions

View File

@@ -14,11 +14,15 @@
#include "blackmisc/identifier.h"
#include "blackmisc/atomicfile.h"
#include <QStandardPaths>
#include <QTimer>
#include <utility>
namespace BlackMisc
{
using Private::CValuePage;
using Private::CDataPageQueue;
class CDataCacheRevision::LockGuard
{
public:
@@ -149,6 +153,39 @@ namespace BlackMisc
});
}
void CDataCache::connectPage(CValuePage *page)
{
auto *queue = new CDataPageQueue(page);
connect(page, &CValuePage::valuesWantToCache, this, &CDataCache::changeValues);
connect(this, &CDataCache::valuesChanged, queue, &CDataPageQueue::queueValuesFromCache, Qt::DirectConnection);
auto *timer = new QTimer(page);
connect(timer, &QTimer::timeout, queue, &CDataPageQueue::trySetQueuedValuesFromCache);
timer->start(0);
}
void CDataPageQueue::queueValuesFromCache(const CValueCachePacket &values, QObject *changedBy)
{
QMutexLocker lock(&m_mutex);
m_queue.push_back(std::make_pair(values, changedBy));
}
void CDataPageQueue::trySetQueuedValuesFromCache()
{
bool locked = m_mutex.tryLock(0);
if (locked)
{
decltype(m_queue) queue;
qSwap(m_queue, queue);
m_mutex.unlock();
for (const auto &pair : queue)
{
m_page->setValuesFromCache(pair.first, pair.second);
}
}
}
CDataCacheSerializer::CDataCacheSerializer(CDataCache *owner, const QString &revisionFileName) :
CContinuousWorker(owner),
m_cache(owner),

View File

@@ -22,6 +22,34 @@
namespace BlackMisc
{
namespace Private
{
/*!
* Decorator for CValuePage which allows incoming remote changes to be queued to allow for more
* flexibility to control how the queue is popped compared to the usual Qt::QueuedConnection.
*/
class BLACKMISC_EXPORT CDataPageQueue : public QObject
{
Q_OBJECT
public:
//! Constructor.
CDataPageQueue(CValuePage *parent) : QObject(parent), m_page(parent) {}
//! Add to the queue to synchronize with a change caused by another page.
//! \threadsafe
void queueValuesFromCache(const BlackMisc::CValueCachePacket &values, QObject *changedBy);
//! Synchronize with changes queued by queueValuesFromCache, if the mutex is not currently locked.
void trySetQueuedValuesFromCache();
private:
CValuePage *m_page = nullptr;
QList<std::pair<CValueCachePacket, QObject*>> m_queue;
QMutex m_mutex;
};
}
class CDataCache;
/*!
@@ -169,6 +197,8 @@ namespace BlackMisc
void saveToStoreAsync(const BlackMisc::CValueCachePacket &values);
void loadFromStoreAsync();
virtual void connectPage(Private::CValuePage *page) override;
QFileSystemWatcher m_watcher;
const QString m_revisionFileName { persistentStore() + "/.rev" };

View File

@@ -246,7 +246,8 @@ namespace BlackMisc
//! \private
void valuesChanged(const BlackMisc::CValueCachePacket &values, QObject *changedBy);
private slots:
protected slots:
//! \private
void changeValues(const BlackMisc::CValueCachePacket &values);
};