Issue #15 Classes for sharing a single value object,

built on top of the lower level API
This commit is contained in:
Mat Sutcliffe
2019-02-26 01:51:54 +00:00
parent 538421b0b7
commit 805cec7caf
6 changed files with 320 additions and 0 deletions

View File

@@ -0,0 +1,37 @@
/* Copyright (C) 2020
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#include "blackmisc/sharedstate/scalarjournal.h"
#include "blackmisc/sharedstate/datalink.h"
namespace BlackMisc
{
namespace SharedState
{
void CGenericScalarJournal::initialize(IDataLink *dataLink)
{
dataLink->publish(m_mutator.data());
dataLink->subscribe(m_observer.data());
m_observer->setEventSubscription(CVariant::from(CAnyMatch()));
m_mutator->postEvent(m_value);
}
CVariant CGenericScalarJournal::handleRequest(const CVariant &param)
{
Q_UNUSED(param)
return m_value;
}
void CGenericScalarJournal::handleEvent(const CVariant &param)
{
m_value = param;
}
}
}

View File

@@ -0,0 +1,65 @@
/* Copyright (C) 2020
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_SHAREDSTATE_SCALARJOURNAL_H
#define BLACKMISC_SHAREDSTATE_SCALARJOURNAL_H
#include "blackmisc/sharedstate/activemutator.h"
#include "blackmisc/sharedstate/passiveobserver.h"
#include "blackmisc/variant.h"
#include "blackmisc/blackmiscexport.h"
#include <QObject>
#include <QMutex>
namespace BlackMisc
{
namespace SharedState
{
class IDataLink;
/*!
* Non-template base class for CScalarJournal.
*/
class BLACKMISC_EXPORT CGenericScalarJournal : public QObject
{
Q_OBJECT
public:
//! Publish using the given transport mechanism.
void initialize(IDataLink *);
protected:
//! Constructor.
CGenericScalarJournal(QObject *parent) : QObject(parent) {}
private:
CVariant handleRequest(const CVariant &param);
void handleEvent(const CVariant &param);
QSharedPointer<CActiveMutator> m_mutator = CActiveMutator::create(this, &CGenericScalarJournal::handleRequest);
QSharedPointer<CPassiveObserver> m_observer = CPassiveObserver::create(this, &CGenericScalarJournal::handleEvent);
CVariant m_value;
};
/*!
* Base class for an object that shares state with a corresponding CScalarObserver subclass object.
* \tparam T Datatype encapsulating the state to be shared.
*/
template <typename T>
class CScalarJournal : public CGenericScalarJournal
{
protected:
//! Constructor.
CScalarJournal(QObject *parent) : CGenericScalarJournal(parent) {}
};
}
}
#endif

View File

@@ -0,0 +1,28 @@
/* Copyright (C) 2017
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#include "blackmisc/sharedstate/scalarmutator.h"
#include "blackmisc/sharedstate/datalink.h"
namespace BlackMisc
{
namespace SharedState
{
void CGenericScalarMutator::initialize(IDataLink *dataLink)
{
dataLink->publish(m_mutator.data());
}
void CGenericScalarMutator::setValue(const CVariant &value)
{
m_mutator->postEvent(value);
}
}
}

View File

@@ -0,0 +1,66 @@
/* Copyright (C) 2017
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_SHAREDSTATE_SCALARMUTATOR_H
#define BLACKMISC_SHAREDSTATE_SCALARMUTATOR_H
#include "blackmisc/sharedstate/passivemutator.h"
#include "blackmisc/variant.h"
#include "blackmisc/blackmiscexport.h"
#include <QObject>
#include <QMutex>
namespace BlackMisc
{
namespace SharedState
{
class IDataLink;
/*!
* Non-template base class for CScalarMutator.
*/
class BLACKMISC_EXPORT CGenericScalarMutator : public QObject
{
Q_OBJECT
public:
//! Publish using the given transport mechanism.
void initialize(IDataLink *);
protected:
//! Constructor.
CGenericScalarMutator(QObject *parent) : QObject(parent) {}
//! Set scalar value as variant.
void setValue(const CVariant &value);
private:
QSharedPointer<CPassiveMutator> m_mutator = CPassiveMutator::create(this);
};
/*!
* Base class for an object that shares state with a corresponding CScalarObserver subclass object.
* \tparam T Datatype encapsulating the state to be shared.
*/
template <typename T>
class CScalarMutator : public CGenericScalarMutator
{
protected:
//! Constructor.
CScalarMutator(QObject *parent) : CGenericScalarMutator(parent) {}
public:
//! Set scalar value.
void setValue(const T &value) { CGenericScalarMutator::setValue(CVariant::from(value)); }
};
}
}
#endif

View File

@@ -0,0 +1,46 @@
/* Copyright (C) 2017
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#include "blackmisc/sharedstate/scalarobserver.h"
#include "blackmisc/sharedstate/datalink.h"
namespace BlackMisc
{
namespace SharedState
{
void CGenericScalarObserver::initialize(IDataLink *dataLink)
{
dataLink->subscribe(m_observer.data());
m_observer->setEventSubscription(CVariant::from(CAnyMatch()));
connect(dataLink->watcher(), &CDataLinkConnectionWatcher::connected, this, &CGenericScalarObserver::reconstruct);
if (dataLink->watcher()->isConnected()) { reconstruct(); }
}
void CGenericScalarObserver::reconstruct()
{
m_observer->requestAsync({}, [this](const CVariant &value) { handleEvent(value); });
}
CVariant CGenericScalarObserver::value() const
{
QMutexLocker lock(&m_valueMutex);
return m_value;
}
void CGenericScalarObserver::handleEvent(const CVariant &param)
{
QMutexLocker lock(&m_valueMutex);
if (m_value == param) { return; }
m_value = param;
lock.unlock();
onGenericValueChanged(param);
}
}
}

View File

@@ -0,0 +1,78 @@
/* Copyright (C) 2017
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution. No part of swift project, including this file, may be copied, modified, propagated,
* or distributed except according to the terms contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_SHAREDSTATE_SCALAROBSERVER_H
#define BLACKMISC_SHAREDSTATE_SCALAROBSERVER_H
#include "blackmisc/sharedstate/activeobserver.h"
#include "blackmisc/variant.h"
#include "blackmisc/blackmiscexport.h"
#include <QObject>
#include <QMutex>
namespace BlackMisc
{
namespace SharedState
{
class IDataLink;
/*!
* Non-template base class for CScalarObserver.
*/
class BLACKMISC_EXPORT CGenericScalarObserver : public QObject
{
Q_OBJECT
public:
//! Subscribe using the given transport mechanism.
void initialize(IDataLink *);
protected:
//! Constructor.
CGenericScalarObserver(QObject *parent) : QObject(parent) {}
//! Get scalar value as variant.
CVariant value() const;
private:
void reconstruct();
void handleEvent(const CVariant &param);
virtual void onGenericValueChanged(const CVariant &value) = 0;
QSharedPointer<CActiveObserver> m_observer = CActiveObserver::create(this, &CGenericScalarObserver::handleEvent);
mutable QMutex m_valueMutex;
CVariant m_value;
};
/*!
* Base class for an object that shares state with a corresponding CScalarMutator subclass object.
* \tparam T Datatype encapsulating the state to be shared.
*/
template <typename T>
class CScalarObserver : public CGenericScalarObserver
{
protected:
//! Constructor.
CScalarObserver(QObject *parent) : CGenericScalarObserver(parent) {}
public:
//! Get scalar value.
T value() const { return CGenericScalarObserver::value().template to<T>(); }
private:
//! Called when the scalar value changes.
virtual void onValueChanged(const T &value) = 0;
virtual void onGenericValueChanged(const CVariant &value) override final { onValueChanged(value.to<T>()); }
};
}
}
#endif