Commit 01eebb29 authored by Thomas BOUTROUE's avatar Thomas BOUTROUE

Much better control of init/reset internally, to avoid memleaks/crashs

- create a Reference<> template to watch for QObject* deletion

- make AbstractLink watch its source/target to act correctly

- cleanup objects/delegate by path mappings on deletion

- don't store chains permanently (uneeded, and avoid checking sanity)

- register objects later at instantiation (after derivate constructors)

- unregister objects sooner at deletion (before ancestor destructors)

- make BasicObject even more basic (do register/unregister in derivates)
parent 7f6ec706
......@@ -4,6 +4,7 @@
#include "IO.h"
#include "Physics.h"
#include "MathUtils.h"
#include "Manager.h"
#include "Link.h"
AbstractActuator::AbstractActuator (const ObjectType::Type type, QObject * parent)
......@@ -30,9 +31,12 @@ AnalogActuator::AnalogActuator (QObject * parent)
connect (this, &AnalogActuator::valRawChanged, this, &AnalogActuator::refreshValSpeed);
connect (this, &AnalogActuator::minRawChanged, this, &AnalogActuator::refreshValSpeed);
connect (this, &AnalogActuator::maxRawChanged, this, &AnalogActuator::refreshValSpeed);
Manager::instance ().registerObject (this);
}
AnalogActuator::~AnalogActuator (void) { }
AnalogActuator::~AnalogActuator (void) {
Manager::instance ().unregisterObject (this);
}
void AnalogActuator::onComponentCompleted (void) {
AbstractActuator::onComponentCompleted ();
......@@ -42,6 +46,7 @@ void AnalogActuator::onComponentCompleted (void) {
if (m_targetLink) {
m_targetLink->set_source (this);
}
Manager::instance ().intializeObject (this);
}
void AnalogActuator::refreshValSpeed (void) {
......@@ -60,15 +65,20 @@ DigitalActuator::DigitalActuator (QObject * parent)
, m_trueLabel ("ON")
, m_falseLabel ("OFF")
, m_sourceLink (Q_NULLPTR)
{ }
{
Manager::instance ().registerObject (this);
}
DigitalActuator::~DigitalActuator (void) { }
DigitalActuator::~DigitalActuator (void) {
Manager::instance ().unregisterObject (this);
}
void DigitalActuator::onComponentCompleted (void) {
AbstractActuator::onComponentCompleted ();
if (m_sourceLink) {
m_sourceLink->set_target (this);
}
Manager::instance ().intializeObject (this);
}
QJsonObject DigitalActuator::exportState (void) const {
......@@ -82,10 +92,16 @@ ActuatorsList::ActuatorsList (QObject * parent)
, m_subObjects (this)
{
m_actuators = new BasicObjectsModel (this);
Manager::instance ().registerObject (this);
}
ActuatorsList::~ActuatorsList (void) {
Manager::instance ().unregisterObject (this);
}
void ActuatorsList::classBegin (void) { }
void ActuatorsList::componentComplete (void) {
m_actuators->appendIf<AbstractActuator> (m_subObjects.items ());
Manager::instance ().intializeObject (this);
}
......@@ -76,6 +76,7 @@ class ActuatorsList : public QObject, public QQmlParserStatus {
public:
explicit ActuatorsList (QObject * parent = Q_NULLPTR);
virtual ~ActuatorsList (void);
void classBegin (void) Q_DECL_FINAL;
void componentComplete (void) Q_DECL_FINAL;
......
......@@ -50,6 +50,7 @@ CanBus::~CanBus (void) {
void CanBus::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
Manager::instance ().intializeObject (this);
}
void CanBus::subscribeRoutineToCanFrameId (RoutineOnCanFrame * routine, int canId) {
......
......@@ -38,6 +38,7 @@ CanOpen::~CanOpen (void) {
void CanOpen::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
m_ready = true;
Manager::instance ().intializeObject (this);
}
void CanOpen::init (void) {
......
......@@ -4,6 +4,7 @@
#include "Sensor.h"
#include "Actuator.h"
#include "MathUtils.h"
#include "Manager.h"
AbstractIO::AbstractIO (const ObjectType::Type type, const ObjectDirection::Type direction, QObject * parent)
: BasicObject (ObjectFamily::IO, parent)
......@@ -36,6 +37,10 @@ QJsonObject AbstractAnalogIO::exportState (void) const {
};
}
void AbstractAnalogIO::onComponentCompleted (void) {
AbstractIO::onComponentCompleted ();
}
AbstractDigitalIO::AbstractDigitalIO (const ObjectDirection::Type direction, QObject * parent)
: AbstractIO (ObjectType::DIGITAL, direction, parent)
, m_value (false)
......@@ -47,11 +52,23 @@ QJsonObject AbstractDigitalIO::exportState (void) const {
};
}
void AbstractDigitalIO::onComponentCompleted (void) {
AbstractIO::onComponentCompleted ();
}
AnalogInput::AnalogInput (QObject * parent)
: AbstractAnalogIO (ObjectDirection::INPUT, parent)
{ }
{
Manager::instance ().registerObject (this);
}
AnalogInput::~AnalogInput (void) { }
AnalogInput::~AnalogInput (void) {
Manager::instance ().unregisterObject (this);
}
void AnalogInput::onComponentCompleted (void) {
Manager::instance ().intializeObject (this);
}
int AnalogInput::getValueInPoints (void) {
return MathUtils::convert (get_valRaw (), get_minRaw (), get_maxRaw (), 0, get_resolutionInPoints () -1);
......@@ -63,9 +80,17 @@ int AnalogInput::getValueInPercents (void) {
AnalogOutput::AnalogOutput (QObject * parent)
: AbstractAnalogIO (ObjectDirection::OUTPUT, parent)
{ }
{
Manager::instance ().registerObject (this);
}
AnalogOutput::~AnalogOutput (void) {
Manager::instance ().unregisterObject (this);
}
AnalogOutput::~AnalogOutput (void) { }
void AnalogOutput::onComponentCompleted (void) {
Manager::instance ().intializeObject (this);
}
void AnalogOutput::setValueInPoints (const int points) {
set_valRaw (MathUtils::convert (points, 0, get_resolutionInPoints () -1, get_minRaw (), get_maxRaw ()));
......@@ -77,12 +102,28 @@ void AnalogOutput::setValueInPercents (const int percents) {
DigitalInput::DigitalInput (QObject * parent)
: AbstractDigitalIO (ObjectDirection::INPUT, parent)
{ }
{
Manager::instance ().registerObject (this);
}
DigitalInput::~DigitalInput (void) {
Manager::instance ().unregisterObject (this);
}
DigitalInput::~DigitalInput (void) { }
void DigitalInput::onComponentCompleted (void) {
Manager::instance ().intializeObject (this);
}
DigitalOutput::DigitalOutput (QObject * parent)
: AbstractDigitalIO (ObjectDirection::OUTPUT, parent)
{ }
{
Manager::instance ().registerObject (this);
}
DigitalOutput::~DigitalOutput (void) { }
DigitalOutput::~DigitalOutput (void) {
Manager::instance ().unregisterObject (this);
}
void DigitalOutput::onComponentCompleted (void) {
Manager::instance ().intializeObject (this);
}
......@@ -39,6 +39,8 @@ public:
explicit AbstractAnalogIO (const ObjectDirection::Type direction = ObjectDirection::UNKNOWN_DIRECTION, QObject * parent = Q_NULLPTR);
QJsonObject exportState (void) const Q_DECL_FINAL;
void onComponentCompleted (void) Q_DECL_OVERRIDE;
};
class AbstractDigitalIO : public AbstractIO {
......@@ -49,6 +51,8 @@ public:
explicit AbstractDigitalIO (const ObjectDirection::Type direction = ObjectDirection::UNKNOWN_DIRECTION, QObject * parent = Q_NULLPTR);
QJsonObject exportState (void) const Q_DECL_FINAL;
void onComponentCompleted (void) Q_DECL_OVERRIDE;
};
class AnalogInput : public AbstractAnalogIO {
......@@ -58,6 +62,8 @@ public:
explicit AnalogInput (QObject * parent = Q_NULLPTR);
virtual ~AnalogInput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
Q_INVOKABLE int getValueInPoints (void);
Q_INVOKABLE int getValueInPercents (void);
};
......@@ -69,6 +75,8 @@ public:
explicit AnalogOutput (QObject * parent = Q_NULLPTR);
virtual ~AnalogOutput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
Q_INVOKABLE void setValueInPoints (const int points);
Q_INVOKABLE void setValueInPercents (const int percents);
};
......@@ -79,6 +87,8 @@ class DigitalInput : public AbstractDigitalIO {
public:
explicit DigitalInput (QObject * parent = Q_NULLPTR);
virtual ~DigitalInput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
};
class DigitalOutput : public AbstractDigitalIO {
......@@ -87,6 +97,8 @@ class DigitalOutput : public AbstractDigitalIO {
public:
explicit DigitalOutput (QObject * parent = Q_NULLPTR);
virtual ~DigitalOutput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
};
#endif // ABSTRACTIO_H
......@@ -9,13 +9,9 @@
BasicObject::BasicObject (const ObjectFamily::Type family, QObject * parent)
: QObject (parent)
, m_family (family)
{
Manager::instance ().registerObject (this);
}
{ }
BasicObject::~BasicObject (void) {
Manager::instance ().unregisterObject (this);
}
BasicObject::~BasicObject (void) { }
void BasicObject::classBegin (void) { }
......@@ -23,9 +19,7 @@ void BasicObject::componentComplete (void) {
onComponentCompleted ();
}
void BasicObject::onComponentCompleted (void) {
Manager::instance ().intializeObject (this);
}
void BasicObject::onComponentCompleted (void) { }
void BasicObject::refreshPath (void) {
QString tmp;
......
......@@ -55,7 +55,95 @@ QML_ENUM_CLASS (ObjectDirection,
OUTPUT,
NB_DIRECTIONS)
class BasicObject : public QObject, public QQmlParserStatus {
template<class T> struct Reference {
public:
explicit Reference (T * ptr = Q_NULLPTR) : _ptr (ptr) {
watch ();
}
T * data (void) {
return _ptr;
}
T * data (void) const {
return _ptr;
}
inline void clear (void) {
set (Q_NULLPTR);
}
inline void operator = (T * ptr) {
set (ptr);
}
inline T * operator -> (void) const {
return _ptr;
}
inline operator T * (void) const {
return _ptr;
}
inline operator bool (void) const {
return (_ptr != Q_NULLPTR);
}
inline bool operator == (T * ptr) const {
return (_ptr == ptr);
}
inline bool operator != (T * ptr) const {
return (_ptr != ptr);
}
protected:
inline void set (T * ptr) {
if (ptr != _ptr) {
unwatch ();
_ptr = ptr;
watch ();
}
}
inline void watch (void) {
if (_ptr) {
_connection = QObject::connect (_ptr, &T::destroyed, [this] (void) {
this->_ptr = Q_NULLPTR;
});
}
}
inline void unwatch (void) {
if (_ptr) {
QObject::disconnect (_connection);
}
}
private:
T * _ptr;
QMetaObject::Connection _connection;
};
template<class T> struct Collection {
public:
explicit Collection (const int reserved) { _.reserve (reserved); }
inline int count (void) const { return _.count (); }
inline void clear (void) { return _.clear (); }
void add (T * item) {
if (item) {
QObject::connect (item, &T::destroyed, [&] (void) {
this->remove (item);
});
_.append (item);
}
}
inline void remove (T * item) { _.removeAll (item); }
typedef typename QList<T *>::const_iterator iterator;
inline iterator begin (void) const { return _.constBegin (); }
inline iterator end (void) const { return _.constEnd (); }
private:
QList<T *> _;
};
class BasicObject : public QObject, public QQmlParserStatus {
Q_OBJECT
Q_INTERFACES (QQmlParserStatus)
QML_CONSTANT_VAR_PROPERTY (ObjectFamily::Type, family)
......
This diff is collapsed.
......@@ -2,6 +2,8 @@
#define LINK_H
#include <QObject>
#include <QMutex>
#include <QMutexLocker>
#include "IdentifiableObject.h"
#include "Transformer.h"
......@@ -30,16 +32,21 @@ public:
explicit AbstractLink (QObject * parent = Q_NULLPTR);
virtual ~AbstractLink (void);
virtual void onComponentCompleted (void) Q_DECL_OVERRIDE;
public slots:
void init (void);
void sync (void);
protected slots:
void onSourceChanged (void);
void onTargetChanged (void);
void onSourceChanged (void);
void onTargetChanged (void);
void onSourceDestroyed (void);
void onTargetDestroyed (void);
protected:
virtual void initHandler (void);
virtual void ensureValid (void);
virtual void syncNormal (void);
virtual void syncReverse (void);
......@@ -49,6 +56,9 @@ protected:
template<typename T> T transformReverse (const T val) {
return (m_transformer ? m_transformer->sourceFromTarget (val) : val);
}
private:
QMutex m_mutex;
};
class LinkPhysicalValueToAnalogSensor : public AbstractLink {
......@@ -60,7 +70,10 @@ public:
explicit LinkPhysicalValueToAnalogSensor (QObject * parent = Q_NULLPTR);
virtual ~LinkPhysicalValueToAnalogSensor (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
......@@ -74,7 +87,10 @@ public:
explicit LinkAnalogSensorToAnalogInput (QObject * parent = Q_NULLPTR);
virtual ~LinkAnalogSensorToAnalogInput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
......@@ -88,7 +104,10 @@ public:
explicit LinkDigitalSensorToDigitalInput (QObject * parent = Q_NULLPTR);
virtual ~LinkDigitalSensorToDigitalInput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
......@@ -102,7 +121,10 @@ public:
explicit LinkAnalogOutputToAnalogActuator (QObject * parent = Q_NULLPTR);
virtual ~LinkAnalogOutputToAnalogActuator (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
......@@ -116,7 +138,10 @@ public:
explicit LinkDigitalOutputToDigitalActuator (QObject * parent = Q_NULLPTR);
virtual ~LinkDigitalOutputToDigitalActuator (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
......@@ -130,7 +155,44 @@ public:
explicit LinkAnalogActuatorToPhysicalValue (QObject * parent = Q_NULLPTR);
virtual ~LinkAnalogActuatorToPhysicalValue (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
class LinkAnalogOutputToAnalogInput : public AbstractLink {
Q_OBJECT
QML_READONLY_PTR_PROPERTY (AnalogOutput, output)
QML_READONLY_PTR_PROPERTY (AnalogInput, input)
public:
explicit LinkAnalogOutputToAnalogInput (QObject * parent = Q_NULLPTR);
virtual ~LinkAnalogOutputToAnalogInput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
class LinkDigitalOutputToDigitalInput : public AbstractLink {
Q_OBJECT
QML_READONLY_PTR_PROPERTY (DigitalOutput, output)
QML_READONLY_PTR_PROPERTY (DigitalInput, input)
public:
explicit LinkDigitalOutputToDigitalInput (QObject * parent = Q_NULLPTR);
virtual ~LinkDigitalOutputToDigitalInput (void);
void onComponentCompleted (void) Q_DECL_FINAL;
void initHandler (void) Q_DECL_FINAL;
void ensureValid (void) Q_DECL_FINAL;
void syncNormal (void) Q_DECL_FINAL;
void syncReverse (void) Q_DECL_FINAL;
};
......
This diff is collapsed.
......@@ -10,7 +10,6 @@
#include <QTimer>
#include <QElapsedTimer>
#include <QQmlEngine>
#include <QPointer>
#include <QQuickItem>
#include "QQmlVariantListModel.h"
......@@ -19,6 +18,8 @@
#include "QQmlPtrPropertyHelpers.h"
#include "QQmlConstRefPropertyHelpers.h"
#include "IdentifiableObject.h"
class CanMessage;
class CanBus;
class CanOpen;
......@@ -63,6 +64,8 @@ class LinkAnalogSensorToAnalogInput;
class LinkDigitalOutputToDigitalActuator;
class LinkDigitalSensorToDigitalInput;
class LinkPhysicalValueToAnalogSensor;
class LinkAnalogOutputToAnalogInput;
class LinkDigitalOutputToDigitalInput;
class PhysicalWorld;
class PhysicalValue;
......@@ -75,63 +78,35 @@ class CustomTransformer;
class Dashboard;
template<class T> struct Collection {
public:
explicit Collection (const int reserved) { _.reserve (reserved); }
inline int count (void) const { return _.count (); }
inline void clear (void) { return _.clear (); }
void add (T * item) {
if (item) {
QObject::connect (item, &T::destroyed, [&] (void) {
this->remove (item);
});
_.append (item);
}
}
inline void remove (T * item) { _.removeAll (item); }
typedef typename QList<T *>::const_iterator iterator;
inline iterator begin (void) const { return _.constBegin (); }
inline iterator end (void) const { return _.constEnd (); }
private:
QList<T *> _;
};
struct AbstractSensorChain { };
struct AbstractSensorChain { };
struct AbstractActuatorChain { };
struct AnalogSensorChain : public AbstractSensorChain {
PhysicalValue * value = Q_NULLPTR;
PhysicalValue * value = Q_NULLPTR;
LinkPhysicalValueToAnalogSensor * linkValueToSensor = Q_NULLPTR;
AnalogSensor * sensor = Q_NULLPTR;
LinkAnalogSensorToAnalogInput * linkSensorToAin = Q_NULLPTR;
AnalogInput * ain = Q_NULLPTR;
AnalogSensor * sensor = Q_NULLPTR;
LinkAnalogSensorToAnalogInput * linkSensorToAin = Q_NULLPTR;
AnalogInput * ain = Q_NULLPTR;
};
struct DigitalSensorChain : public AbstractSensorChain {
DigitalSensor * sensor = Q_NULLPTR;
DigitalSensor * sensor = Q_NULLPTR;
LinkDigitalSensorToDigitalInput * linkSensorToDin = Q_NULLPTR;
DigitalInput * din = Q_NULLPTR;
DigitalInput * din = Q_NULLPTR;
};
struct AnalogActuatorChain : public AbstractActuatorChain {
AnalogOutput * aout = Q_NULLPTR;
LinkAnalogOutputToAnalogActuator * linkAoutToActuator = Q_NULLPTR;
AnalogActuator * actuator = Q_NULLPTR;
AnalogOutput * aout = Q_NULLPTR;
LinkAnalogOutputToAnalogActuator * linkAoutToActuator = Q_NULLPTR;
AnalogActuator * actuator = Q_NULLPTR;
LinkAnalogActuatorToPhysicalValue * linkActuatorToValue = Q_NULLPTR;
PhysicalValue * value = Q_NULLPTR;
PhysicalValue * value = Q_NULLPTR;
};
struct DigitalActuatorChain : public AbstractActuatorChain {
DigitalOutput * dout = Q_NULLPTR;
DigitalOutput * dout = Q_NULLPTR;
LinkDigitalOutputToDigitalActuator * linkDoutToActuator = Q_NULLPTR;
DigitalActuator * actuator = Q_NULLPTR;
DigitalActuator * actuator = Q_NULLPTR;
};
class Dictionary : public QObject {
......@@ -199,7 +174,7 @@ protected slots:
void doBuildChains (void);
protected:
QPointer<PhysicalWorld> m_physicalWorld;
Reference<PhysicalWorld> m_physicalWorld;
Collection<BasicObject> m_basicObjects;
......@@ -219,6 +194,8 @@ protected:
Collection<LinkDigitalOutputToDigitalActuator> m_linksDigitalOutputToDigitalActuator;
Collection<LinkDigitalSensorToDigitalInput> m_linksDigitalSensorToDigitalInput;
Collection<LinkPhysicalValueToAnalogSensor> m_linksPhysicalValueToAnalogSensor;
Collection<LinkAnalogOutputToAnalogInput> m_linksAnalogOutputToAnalogInput;
Collection<LinkDigitalOutputToDigitalInput> m_linksDigitalOutputToDigitalInput;
Collection<AbstractTransformer> m_transformers;
Collection<AffineTransformer> m_affineTransformers;
......@@ -262,10 +239,6 @@ private:
QElapsedTimer m_chrono;
QSet<QObject *> m_objectsInstances;
QStack<QObject *> m_objectsToInit;
QList<AnalogSensorChain *> m_analogSensorChains;
QList<DigitalSensorChain *> m_digitalSensorChains;
QList<AnalogActuatorChain *> m_analogActuatorChains;
QList<DigitalActuatorChain *> m_digitalActuatorChains;
explicit Manager (void);
};
......
......@@ -4,6 +4,7 @@
#include "IO.h"
#include "Routine.h"
#include "CanOpen.h"
#include "Manager.h"
#include "Memory.h"
#include "CanDriverQmlWrapper.h"
......@@ -12,13 +13,17 @@ Board::Board (QObject * parent)
, m_subObjects (this)
{
m_ios = new BasicObjectsModel (this);
Manager::instance ().registerObject (this);
}
Board::~Board (void) { }
Board::~Board (void) {
Manager::instance ().unregisterObject (this);
}
void Board::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
m_ios->appendIf<AbstractIO> (m_subObjects.items ());
Manager::instance ().intializeObject (this);
}
Node::Node (QObject * parent)
......@@ -29,14 +34,18 @@ Node::Node (QObject * parent)
m_memory = new Memory (this);
m_boards = new BasicObjectsModel (this);
m_routines = new BasicObjectsModel (this);
Manager::instance ().registerObject (this);
}
Node::~Node (void) { }
Node::~Node (void) {
Manager::instance ().unregisterObject (this);
}
void Node::onComponentCompleted (void) {
BasicObject::onComponentCompleted ();
m_boards->appendIf<Board> (m_subObjects.items ());
m_routines->appendIf<AbstractRoutine> (m_subObjects.items ());
Manager::instance ().intializeObject (this);
}
void Node::init (void) {
......@@ -62,10 +71,16 @@ NodesList::NodesList (QObject * parent)
, m_subObjects (this)
{
m_nodes = new BasicObjectsModel (this);
Manager::instance ().registerObject (this);
}
NodesList::~NodesList (void) {
Manager::instance ().unregisterObject (this);
}
void NodesList::classBegin (void) { }
void NodesList::componentComplete (void) {
m_nodes->appendIf<Node> (m_subObjects.items ());
Manager::instance ().intializeObject (this);
}