diff options
author | Paul Lemire <paul.lemire@kdab.com> | 2016-05-20 17:11:37 +0200 |
---|---|---|
committer | Sean Harmer <sean.harmer@kdab.com> | 2016-05-23 16:31:55 +0000 |
commit | 073930f2ef030b3019c323999d910185f4639d9b (patch) | |
tree | 0c2bba252f7a92d4f3841fbe42eeca27e2a8a838 /src/core/nodes/qnode_p.h | |
parent | 15dace7c02bc5acdf02f94c8be08fec1a792383c (diff) |
Shared node bookkeeping
Any time a property references a QNode there is a risk that the node gets
destroyed and then the property is left pointing to a dangling pointer.
To handle such cases, setters of such properties are able to use a helper
that internally connect QObject::destroyed signal to a setter removal method.
Change-Id: I42428c851d0e3d2d88ab0cf6a5b75605334ec648
Task-number: QTBUG-53456
Reviewed-by: Sean Harmer <sean.harmer@kdab.com>
Diffstat (limited to 'src/core/nodes/qnode_p.h')
-rw-r--r-- | src/core/nodes/qnode_p.h | 29 |
1 files changed, 29 insertions, 0 deletions
diff --git a/src/core/nodes/qnode_p.h b/src/core/nodes/qnode_p.h index e290ffe32..8f48dd728 100644 --- a/src/core/nodes/qnode_p.h +++ b/src/core/nodes/qnode_p.h @@ -57,6 +57,7 @@ #include <Qt3DCore/private/qchangearbiter_p.h> #include <Qt3DCore/private/qt3dcore_global_p.h> #include "propertychangehandler_p.h" +#include <functional> QT_BEGIN_NAMESPACE @@ -100,6 +101,33 @@ public: static QNodePrivate *get(QNode *q); static void nodePtrDeleter(QNode *q); + template<typename Caller, typename NodeType> + using DestructionFunction = void (Caller::*)(NodeType *); + + template<typename Caller, typename NodeType, typename PropertyType> + void registerDestructionHelper(NodeType *, DestructionFunction<Caller, NodeType>, PropertyType); + + template<typename Caller, typename NodeType> + void registerDestructionHelper(NodeType *node, DestructionFunction<Caller, NodeType> func, NodeType *&) + { + // If the node is destoyed, we make sure not to keep a dangling pointer to it + auto f = std::bind(func, static_cast<Caller *>(q_func()), nullptr); + m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f)); + } + + template<typename Caller, typename NodeType> + void registerDestructionHelper(NodeType *node, DestructionFunction<Caller, NodeType> func, QVector<NodeType*> &) + { + // If the node is destoyed, we make sure not to keep a dangling pointer to it + auto f = std::bind(func, static_cast<Caller *>(q_func()), node); + m_destructionConnections.insert(node, QObject::connect(node, &QNode::nodeDestroyed, f)); + } + + void unregisterDestructionHelper(QNode *node) + { + QObject::disconnect(m_destructionConnections.take(node)); + } + private: void notifyCreationChange(); void notifyDestructionChangesAndRemoveFromScene(); @@ -118,6 +146,7 @@ private: friend class PropertyChangeHandler<QNodePrivate>; bool m_propertyChangesSetup; PropertyChangeHandler<QNodePrivate> m_signals; + QHash<QNode *, QMetaObject::Connection> m_destructionConnections; }; } // namespace Qt3DCore |