diff options
author | Chris Adams <christopher.adams@nokia.com> | 2011-08-26 13:54:00 +1000 |
---|---|---|
committer | Qt by Nokia <qt-info@nokia.com> | 2011-09-06 08:29:53 +0200 |
commit | 08e829e3a9dae0230678a8471275cebb4c8fb54e (patch) | |
tree | fdbbc6b718ef026cac7c929ca710277478a4739c /tests/auto/declarative/qdeclarativeecmascript/testtypes.h | |
parent | 0c0f03e2b9756afb4e868a76734cc90102218f0a (diff) |
Add garbage collector prologue callback to qv8engine
This commit provides a generic way to manage persistent handles
created by QML so that circular references don't cause leaks, by
utilising v8's garbage collector callbacks.
Change-Id: Ia898197fdf5d86b90915b835ce3e532f7d400de4
Reviewed-on: http://codereview.qt.nokia.com/3688
Reviewed-by: Qt Sanity Bot <qt_sanity_bot@ovi.com>
Reviewed-by: Aaron Kennedy <aaron.kennedy@nokia.com>
Diffstat (limited to 'tests/auto/declarative/qdeclarativeecmascript/testtypes.h')
-rw-r--r-- | tests/auto/declarative/qdeclarativeecmascript/testtypes.h | 105 |
1 files changed, 105 insertions, 0 deletions
diff --git a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h index 2738ee3d60..52b74affa8 100644 --- a/tests/auto/declarative/qdeclarativeecmascript/testtypes.h +++ b/tests/auto/declarative/qdeclarativeecmascript/testtypes.h @@ -57,6 +57,9 @@ #include <QtDeclarative/qdeclarativescriptstring.h> #include <QtDeclarative/qdeclarativecomponent.h> +#include <private/qv8gccallback_p.h> +#include <private/qdeclarativeengine_p.h> + class MyQmlAttachedObject : public QObject { Q_OBJECT @@ -966,6 +969,108 @@ private: int m_methodCallCount; }; +class CircularReferenceObject : public QObject, + public QV8GCCallback::Node +{ + Q_OBJECT + +public: + CircularReferenceObject(QObject *parent = 0) + : QObject(parent), QV8GCCallback::Node(callback), m_referenced(0), m_dtorCount(0) + { + QV8GCCallback::addGcCallbackNode(this); + } + + ~CircularReferenceObject() + { + if (m_dtorCount) *m_dtorCount = *m_dtorCount + 1; + } + + Q_INVOKABLE void setDtorCount(int *dtorCount) + { + m_dtorCount = dtorCount; + } + + Q_INVOKABLE CircularReferenceObject *generate(QObject *parent = 0) + { + CircularReferenceObject *retn = new CircularReferenceObject(parent); + retn->m_dtorCount = m_dtorCount; + return retn; + } + + Q_INVOKABLE void addReference(QObject *other) + { + m_referenced = other; + } + + static void callback(QV8GCCallback::Referencer *r, QV8GCCallback::Node *n) + { + CircularReferenceObject *cro = static_cast<CircularReferenceObject*>(n); + if (cro->m_referenced) { + r->addRelationship(cro, cro->m_referenced); + } + } + +private: + QObject *m_referenced; + int *m_dtorCount; +}; +Q_DECLARE_METATYPE(CircularReferenceObject*) + +class CircularReferenceHandle : public QObject, + public QV8GCCallback::Node +{ + Q_OBJECT + +public: + CircularReferenceHandle(QObject *parent = 0) + : QObject(parent), QV8GCCallback::Node(gccallback), m_dtorCount(0) + { + QV8GCCallback::addGcCallbackNode(this); + } + + ~CircularReferenceHandle() + { + if (m_dtorCount) *m_dtorCount = *m_dtorCount + 1; + } + + Q_INVOKABLE void setDtorCount(int *dtorCount) + { + m_dtorCount = dtorCount; + } + + Q_INVOKABLE CircularReferenceHandle *generate(QObject *parent = 0) + { + CircularReferenceHandle *retn = new CircularReferenceHandle(parent); + retn->m_dtorCount = m_dtorCount; + return retn; + } + + Q_INVOKABLE void addReference(v8::Persistent<v8::Value> handle) + { + m_referenced = qPersistentNew(handle); + m_referenced.MakeWeak(static_cast<void*>(this), wrcallback); + } + + static void wrcallback(v8::Persistent<v8::Value> handle, void *params) + { + CircularReferenceHandle *crh = static_cast<CircularReferenceHandle*>(params); + qPersistentDispose(handle); + crh->m_referenced.Clear(); + } + + static void gccallback(QV8GCCallback::Referencer *r, QV8GCCallback::Node *n) + { + CircularReferenceHandle *crh = static_cast<CircularReferenceHandle*>(n); + r->addRelationship(crh, crh->m_referenced); + } + +private: + v8::Persistent<v8::Value> m_referenced; + int *m_dtorCount; +}; +Q_DECLARE_METATYPE(CircularReferenceHandle*) + void registerTypes(); #endif // TESTTYPES_H |