aboutsummaryrefslogtreecommitdiffstats
path: root/src/declarative/qml/ftw
diff options
context:
space:
mode:
authorAaron Kennedy <aaron.kennedy@nokia.com>2011-09-05 17:31:41 +1000
committerQt by Nokia <qt-info@nokia.com>2011-09-29 06:12:49 +0200
commit703c808a5649169dd6b9605af273374cd62951d1 (patch)
tree7248cc72bfa632a51c814d6622f0b12a7f2bd443 /src/declarative/qml/ftw
parent600e56ad053362dd5d4150f5dec6b93c2fee575b (diff)
Asynchronous component instantiation
This introduces two main: * the QML compiler executes in a separate thread * item instantiation can be interrupted and resumed to allow it to be split across multiple frames. Task-number: QTBUG-21151 Change-Id: I9631c62bb77da3a2e0c37f0da3719533fdce4fef Reviewed-on: http://codereview.qt-project.org/5676 Reviewed-by: Martin Jones <martin.jones@nokia.com>
Diffstat (limited to 'src/declarative/qml/ftw')
-rw-r--r--src/declarative/qml/ftw/ftw.pri4
-rw-r--r--src/declarative/qml/ftw/qdeclarativerefcount.cpp70
-rw-r--r--src/declarative/qml/ftw/qdeclarativerefcount_p.h58
-rw-r--r--src/declarative/qml/ftw/qdeclarativethread.cpp359
-rw-r--r--src/declarative/qml/ftw/qdeclarativethread_p.h318
-rw-r--r--src/declarative/qml/ftw/qfieldlist_p.h29
-rw-r--r--src/declarative/qml/ftw/qfinitestack_p.h186
7 files changed, 947 insertions, 77 deletions
diff --git a/src/declarative/qml/ftw/ftw.pri b/src/declarative/qml/ftw/ftw.pri
index d6e7df53b2..2d6729bd79 100644
--- a/src/declarative/qml/ftw/ftw.pri
+++ b/src/declarative/qml/ftw/ftw.pri
@@ -11,12 +11,14 @@ HEADERS += \
$$PWD/qfieldlist_p.h \
$$PWD/qfastmetabuilder_p.h \
$$PWD/qhashfield_p.h \
+ $$PWD/qdeclarativethread_p.h \
+ $$PWD/qfinitestack_p.h \
SOURCES += \
$$PWD/qintrusivelist.cpp \
$$PWD/qmetaobjectbuilder.cpp \
$$PWD/qhashedstring.cpp \
- $$PWD/qdeclarativerefcount.cpp \
$$PWD/qdeclarativepool.cpp \
$$PWD/qfastmetabuilder.cpp \
+ $$PWD/qdeclarativethread.cpp \
diff --git a/src/declarative/qml/ftw/qdeclarativerefcount.cpp b/src/declarative/qml/ftw/qdeclarativerefcount.cpp
deleted file mode 100644
index a17d5b7142..0000000000
--- a/src/declarative/qml/ftw/qdeclarativerefcount.cpp
+++ /dev/null
@@ -1,70 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
-** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
-**
-** This file is part of the QtDeclarative module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** GNU Lesser General Public License Usage
-** This file may be used under the terms of the GNU Lesser General Public
-** License version 2.1 as published by the Free Software Foundation and
-** appearing in the file LICENSE.LGPL included in the packaging of this
-** file. Please review the following information to ensure the GNU Lesser
-** General Public License version 2.1 requirements will be met:
-** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
-**
-** In addition, as a special exception, Nokia gives you certain additional
-** rights. These rights are described in the Nokia Qt LGPL Exception
-** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU General
-** Public License version 3.0 as published by the Free Software Foundation
-** and appearing in the file LICENSE.GPL included in the packaging of this
-** file. Please review the following information to ensure the GNU General
-** Public License version 3.0 requirements will be met:
-** http://www.gnu.org/copyleft/gpl.html.
-**
-** Other Usage
-** Alternatively, this file may be used in accordance with the terms and
-** conditions contained in a signed written agreement between you and Nokia.
-**
-**
-**
-**
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "private/qdeclarativerefcount_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QDeclarativeRefCount::QDeclarativeRefCount()
-: refCount(1)
-{
-}
-
-QDeclarativeRefCount::~QDeclarativeRefCount()
-{
-}
-
-void QDeclarativeRefCount::addref()
-{
- Q_ASSERT(refCount > 0);
- ++refCount;
-}
-
-void QDeclarativeRefCount::release()
-{
- Q_ASSERT(refCount > 0);
- --refCount;
- if (refCount == 0)
- delete this;
-}
-
-QT_END_NAMESPACE
-
diff --git a/src/declarative/qml/ftw/qdeclarativerefcount_p.h b/src/declarative/qml/ftw/qdeclarativerefcount_p.h
index 381327098c..8ae9618f30 100644
--- a/src/declarative/qml/ftw/qdeclarativerefcount_p.h
+++ b/src/declarative/qml/ftw/qdeclarativerefcount_p.h
@@ -54,6 +54,7 @@
//
#include <QtCore/qglobal.h>
+#include <QtCore/qatomic.h>
QT_BEGIN_HEADER
@@ -61,16 +62,19 @@ QT_BEGIN_NAMESPACE
QT_MODULE(Declarative)
-class Q_DECLARATIVE_EXPORT QDeclarativeRefCount
+class QDeclarativeRefCount
{
public:
- QDeclarativeRefCount();
- virtual ~QDeclarativeRefCount();
- void addref();
- void release();
+ inline QDeclarativeRefCount();
+ inline virtual ~QDeclarativeRefCount();
+ inline void addref();
+ inline void release();
+
+protected:
+ inline virtual void destroy();
private:
- int refCount;
+ QAtomicInt refCount;
};
template<class T>
@@ -92,10 +96,40 @@ public:
inline operator T*() const { return o; }
inline T* data() const { return o; }
+ inline QDeclarativeRefPointer<T> &take(T *);
+
private:
T *o;
};
+QDeclarativeRefCount::QDeclarativeRefCount()
+: refCount(1)
+{
+}
+
+QDeclarativeRefCount::~QDeclarativeRefCount()
+{
+ Q_ASSERT(refCount == 0);
+}
+
+void QDeclarativeRefCount::addref()
+{
+ Q_ASSERT(refCount > 0);
+ refCount.ref();
+}
+
+void QDeclarativeRefCount::release()
+{
+ Q_ASSERT(refCount > 0);
+ if (!refCount.deref())
+ destroy();
+}
+
+void QDeclarativeRefCount::destroy()
+{
+ delete this;
+}
+
template<class T>
QDeclarativeRefPointer<T>::QDeclarativeRefPointer()
: o(0)
@@ -140,6 +174,18 @@ QDeclarativeRefPointer<T> &QDeclarativeRefPointer<T>::operator=(T *other)
return *this;
}
+/*!
+Takes ownership of \a other. take() does *not* add a reference, as it assumes ownership
+of the callers reference of other.
+*/
+template<class T>
+QDeclarativeRefPointer<T> &QDeclarativeRefPointer<T>::take(T *other)
+{
+ if (o) o->release();
+ o = other;
+ return *this;
+}
+
QT_END_NAMESPACE
QT_END_HEADER
diff --git a/src/declarative/qml/ftw/qdeclarativethread.cpp b/src/declarative/qml/ftw/qdeclarativethread.cpp
new file mode 100644
index 0000000000..4a21c90bf1
--- /dev/null
+++ b/src/declarative/qml/ftw/qdeclarativethread.cpp
@@ -0,0 +1,359 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include "qdeclarativethread_p.h"
+
+#include <private/qfieldlist_p.h>
+
+#include <QtCore/qmutex.h>
+#include <QtCore/qthread.h>
+#include <QtCore/qcoreevent.h>
+#include <QtCore/qwaitcondition.h>
+#include <QtCore/qcoreapplication.h>
+
+QT_BEGIN_NAMESPACE
+
+class QDeclarativeThreadPrivate : public QThread
+{
+public:
+ QDeclarativeThreadPrivate(QDeclarativeThread *);
+ QDeclarativeThread *q;
+
+ virtual void run();
+
+ inline void lock() { _mutex.lock(); }
+ inline void unlock() { _mutex.unlock(); }
+ inline void wait() { _wait.wait(&_mutex); }
+ inline void wakeOne() { _wait.wakeOne(); }
+ inline void wakeAll() { _wait.wakeAll(); }
+
+ quint32 m_threadProcessing:1; // Set when the thread is processing messages
+ quint32 m_mainProcessing:1; // Set when the main thread is processing messages
+ quint32 m_shutdown:1; // Set by main thread to request a shutdown
+ quint32 m_mainThreadWaiting:1; // Set by main thread if it is waiting for the message queue to empty
+
+ typedef QFieldList<QDeclarativeThread::Message, &QDeclarativeThread::Message::next> MessageList;
+ MessageList threadList;
+ MessageList mainList;
+
+ QDeclarativeThread::Message *mainSync;
+
+ void triggerMainEvent();
+ void triggerThreadEvent();
+
+ void mainEvent();
+ void threadEvent();
+
+protected:
+ virtual bool event(QEvent *);
+
+private:
+ struct MainObject : public QObject {
+ MainObject(QDeclarativeThreadPrivate *p);
+ virtual bool event(QEvent *e);
+ QDeclarativeThreadPrivate *p;
+ };
+ MainObject m_mainObject;
+
+ QMutex _mutex;
+ QWaitCondition _wait;
+};
+
+QDeclarativeThreadPrivate::MainObject::MainObject(QDeclarativeThreadPrivate *p)
+: p(p)
+{
+}
+
+// Trigger mainEvent in main thread. Must be called from thread.
+void QDeclarativeThreadPrivate::triggerMainEvent()
+{
+ Q_ASSERT(q->isThisThread());
+ QCoreApplication::postEvent(&m_mainObject, new QEvent(QEvent::User));
+}
+
+// Trigger even in thread. Must be called from main thread.
+void QDeclarativeThreadPrivate::triggerThreadEvent()
+{
+ Q_ASSERT(!q->isThisThread());
+ QCoreApplication::postEvent(this, new QEvent(QEvent::User));
+}
+
+bool QDeclarativeThreadPrivate::MainObject::event(QEvent *e)
+{
+ if (e->type() == QEvent::User)
+ p->mainEvent();
+ return QObject::event(e);
+}
+
+QDeclarativeThreadPrivate::QDeclarativeThreadPrivate(QDeclarativeThread *q)
+: q(q), m_threadProcessing(false), m_mainProcessing(false), m_shutdown(false),
+ m_mainThreadWaiting(false), mainSync(0), m_mainObject(this)
+{
+}
+
+bool QDeclarativeThreadPrivate::event(QEvent *e)
+{
+ if (e->type() == QEvent::User)
+ threadEvent();
+ return QThread::event(e);
+}
+
+void QDeclarativeThreadPrivate::run()
+{
+ lock();
+
+ wakeOne();
+
+ unlock();
+
+ q->startupThread();
+ exec();
+}
+
+void QDeclarativeThreadPrivate::mainEvent()
+{
+ lock();
+
+ m_mainProcessing = true;
+
+ while (!mainList.isEmpty() || mainSync) {
+ bool isSync = mainSync != 0;
+ QDeclarativeThread::Message *message = isSync?mainSync:mainList.takeFirst();
+ unlock();
+
+ message->call(q);
+ delete message;
+
+ lock();
+
+ if (isSync) {
+ mainSync = 0;
+ wakeOne();
+ }
+ }
+
+ m_mainProcessing = false;
+
+ unlock();
+}
+
+void QDeclarativeThreadPrivate::threadEvent()
+{
+ lock();
+
+ if (m_shutdown) {
+ quit();
+ wakeOne();
+ unlock();
+ q->shutdownThread();
+ } else {
+ m_threadProcessing = true;
+
+ while (!threadList.isEmpty()) {
+ QDeclarativeThread::Message *message = threadList.first();
+
+ unlock();
+
+ message->call(q);
+
+ lock();
+
+ delete threadList.takeFirst();
+ }
+
+ wakeOne();
+
+ m_threadProcessing = false;
+
+ unlock();
+ }
+}
+
+QDeclarativeThread::QDeclarativeThread()
+: d(new QDeclarativeThreadPrivate(this))
+{
+ d->lock();
+ d->start();
+ d->wait();
+ d->unlock();
+ d->moveToThread(d);
+
+}
+
+QDeclarativeThread::~QDeclarativeThread()
+{
+ delete d;
+}
+
+void QDeclarativeThread::shutdown()
+{
+ d->lock();
+ Q_ASSERT(!d->m_shutdown);
+ d->m_shutdown = true;
+ if (d->threadList.isEmpty() && d->m_threadProcessing == false)
+ d->triggerThreadEvent();
+ d->wait();
+ d->unlock();
+ d->QThread::wait();
+}
+
+void QDeclarativeThread::lock()
+{
+ d->lock();
+}
+
+void QDeclarativeThread::unlock()
+{
+ d->unlock();
+}
+
+void QDeclarativeThread::wakeOne()
+{
+ d->wakeOne();
+}
+
+void QDeclarativeThread::wakeAll()
+{
+ d->wakeAll();
+}
+
+void QDeclarativeThread::wait()
+{
+ d->wait();
+}
+
+bool QDeclarativeThread::isThisThread() const
+{
+ return QThread::currentThread() == d;
+}
+
+QThread *QDeclarativeThread::thread() const
+{
+ return const_cast<QThread *>(static_cast<const QThread *>(d));
+}
+
+// Called when the thread starts. Do startup stuff in here.
+void QDeclarativeThread::startupThread()
+{
+}
+
+// Called when the thread shuts down. Do cleanup in here.
+void QDeclarativeThread::shutdownThread()
+{
+}
+
+void QDeclarativeThread::internalCallMethodInThread(Message *message)
+{
+ Q_ASSERT(!isThisThread());
+ d->lock();
+ Q_ASSERT(d->m_mainThreadWaiting == false);
+
+ bool wasEmpty = d->threadList.isEmpty();
+ d->threadList.append(message);
+ if (wasEmpty && d->m_threadProcessing == false)
+ d->triggerThreadEvent();
+
+ d->m_mainThreadWaiting = true;
+
+ do {
+ if (d->mainSync) {
+ QDeclarativeThread::Message *message = d->mainSync;
+ unlock();
+ message->call(this);
+ delete message;
+ lock();
+ d->mainSync = 0;
+ wakeOne();
+ } else {
+ d->wait();
+ }
+ } while (d->mainSync || !d->threadList.isEmpty());
+
+ d->m_mainThreadWaiting = false;
+ d->unlock();
+}
+
+void QDeclarativeThread::internalCallMethodInMain(Message *message)
+{
+ Q_ASSERT(isThisThread());
+
+ d->lock();
+
+ Q_ASSERT(d->mainSync == 0);
+ d->mainSync = message;
+
+ if (d->m_mainThreadWaiting) {
+ d->wakeOne();
+ } else if (d->m_mainProcessing) {
+ // Do nothing - it is already looping
+ } else {
+ d->triggerMainEvent();
+ }
+
+ while (d->mainSync && !d->m_shutdown)
+ d->wait();
+
+ d->unlock();
+}
+
+void QDeclarativeThread::internalPostMethodToThread(Message *message)
+{
+ Q_ASSERT(!isThisThread());
+ d->lock();
+ bool wasEmpty = d->threadList.isEmpty();
+ d->threadList.append(message);
+ if (wasEmpty && d->m_threadProcessing == false)
+ d->triggerThreadEvent();
+ d->unlock();
+}
+
+void QDeclarativeThread::internalPostMethodToMain(Message *message)
+{
+ Q_ASSERT(isThisThread());
+ d->lock();
+ bool wasEmpty = d->mainList.isEmpty();
+ d->mainList.append(message);
+ if (wasEmpty && d->m_mainProcessing == false)
+ d->triggerMainEvent();
+ d->unlock();
+}
+
+QT_END_NAMESPACE
diff --git a/src/declarative/qml/ftw/qdeclarativethread_p.h b/src/declarative/qml/ftw/qdeclarativethread_p.h
new file mode 100644
index 0000000000..2f5815568e
--- /dev/null
+++ b/src/declarative/qml/ftw/qdeclarativethread_p.h
@@ -0,0 +1,318 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QDECLARATIVETHREAD_P_H
+#define QDECLARATIVETHREAD_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+
+#include <QtCore/qglobal.h>
+
+#include <private/qintrusivelist_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QThread;
+
+class QDeclarativeThreadPrivate;
+class QDeclarativeThread
+{
+public:
+ QDeclarativeThread();
+ virtual ~QDeclarativeThread();
+ void shutdown();
+
+ void lock();
+ void unlock();
+ void wakeOne();
+ void wakeAll();
+ void wait();
+
+ QThread *thread() const;
+ bool isThisThread() const;
+
+ // Synchronously invoke a method in the thread
+ template<class O>
+ inline void callMethodInThread(void (O::*Member)());
+ template<typename T, class V, class O>
+ inline void callMethodInThread(void (O::*Member)(V), const T &);
+ template<typename T, typename T2, class V, class V2, class O>
+ inline void callMethodInThread(void (O::*Member)(V, V2), const T &, const T2 &);
+
+ // Synchronously invoke a method in the main thread. If the main thread is
+ // blocked in a callMethodInThread() call, the call is made from within that
+ // call.
+ template<class O>
+ inline void callMethodInMain(void (O::*Member)());
+ template<typename T, class V, class O>
+ inline void callMethodInMain(void (O::*Member)(V), const T &);
+ template<typename T, typename T2, class V, class V2, class O>
+ inline void callMethodInMain(void (O::*Member)(V, V2), const T &, const T2 &);
+
+ // Asynchronously invoke a method in the thread.
+ template<class O>
+ inline void postMethodToThread(void (O::*Member)());
+ template<typename T, class V, class O>
+ inline void postMethodToThread(void (O::*Member)(V), const T &);
+ template<typename T, typename T2, class V, class V2, class O>
+ inline void postMethodToThread(void (O::*Member)(V, V2), const T &, const T2 &);
+
+ // Asynchronously invoke a method in the main thread.
+ template<class O>
+ inline void postMethodToMain(void (O::*Member)());
+ template<typename T, class V, class O>
+ inline void postMethodToMain(void (O::*Member)(V), const T &);
+ template<typename T, typename T2, class V, class V2, class O>
+ inline void postMethodToMain(void (O::*Member)(V, V2), const T &, const T2 &);
+
+protected:
+ virtual void startupThread();
+ virtual void shutdownThread();
+
+private:
+ friend class QDeclarativeThreadPrivate;
+
+ struct Message {
+ Message() : next(0) {}
+ virtual ~Message() {}
+ Message *next;
+ virtual void call(QDeclarativeThread *) = 0;
+ };
+ void internalCallMethodInThread(Message *);
+ void internalCallMethodInMain(Message *);
+ void internalPostMethodToThread(Message *);
+ void internalPostMethodToMain(Message *);
+ QDeclarativeThreadPrivate *d;
+};
+
+template<class O>
+void QDeclarativeThread::callMethodInThread(void (O::*Member)())
+{
+ struct I : public Message {
+ void (O::*Member)();
+ I(void (O::*Member)()) : Member(Member) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)();
+ }
+ };
+ internalCallMethodInThread(new I(Member));
+}
+
+template<typename T, class V, class O>
+void QDeclarativeThread::callMethodInThread(void (O::*Member)(V), const T &arg)
+{
+ struct I : public Message {
+ void (O::*Member)(V);
+ T arg;
+ I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg);
+ }
+ };
+ internalCallMethodInThread(new I(Member, arg));
+}
+
+template<typename T, typename T2, class V, class V2, class O>
+void QDeclarativeThread::callMethodInThread(void (O::*Member)(V, V2), const T &arg, const T2 &arg2)
+{
+ struct I : public Message {
+ void (O::*Member)(V, V2);
+ T arg;
+ T2 arg2;
+ I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg, arg2);
+ }
+ };
+ internalCallMethodInThread(new I(Member, arg, arg2));
+}
+
+template<class O>
+void QDeclarativeThread::callMethodInMain(void (O::*Member)())
+{
+ struct I : public Message {
+ void (O::*Member)();
+ I(void (O::*Member)()) : Member(Member) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)();
+ }
+ };
+ internalCallMethodInMain(new I(Member));
+}
+
+template<typename T, class V, class O>
+void QDeclarativeThread::callMethodInMain(void (O::*Member)(V), const T &arg)
+{
+ struct I : public Message {
+ void (O::*Member)(V);
+ T arg;
+ I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg);
+ }
+ };
+ internalCallMethodInMain(new I(Member, arg));
+}
+
+template<typename T, typename T2, class V, class V2, class O>
+void QDeclarativeThread::callMethodInMain(void (O::*Member)(V, V2), const T &arg, const T2 &arg2)
+{
+ struct I : public Message {
+ void (O::*Member)(V, V2);
+ T arg;
+ T2 arg2;
+ I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg, arg2);
+ }
+ };
+ internalCallMethodInMain(new I(Member, arg, arg2));
+}
+
+template<class O>
+void QDeclarativeThread::postMethodToThread(void (O::*Member)())
+{
+ struct I : public Message {
+ void (O::*Member)();
+ I(void (O::*Member)()) : Member(Member) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)();
+ }
+ };
+ internalPostMethodToThread(new I(Member));
+}
+
+template<typename T, class V, class O>
+void QDeclarativeThread::postMethodToThread(void (O::*Member)(V), const T &arg)
+{
+ struct I : public Message {
+ void (O::*Member)(V);
+ T arg;
+ I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg);
+ }
+ };
+ internalPostMethodToThread(new I(Member, arg));
+}
+
+template<typename T, typename T2, class V, class V2, class O>
+void QDeclarativeThread::postMethodToThread(void (O::*Member)(V, V2), const T &arg, const T2 &arg2)
+{
+ struct I : public Message {
+ void (O::*Member)(V, V2);
+ T arg;
+ T2 arg2;
+ I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg, arg2);
+ }
+ };
+ internalPostMethodToThread(new I(Member, arg, arg2));
+}
+
+template<class O>
+void QDeclarativeThread::postMethodToMain(void (O::*Member)())
+{
+ struct I : public Message {
+ void (O::*Member)();
+ I(void (O::*Member)()) : Member(Member) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)();
+ }
+ };
+ internalPostMethodToMain(new I(Member));
+}
+
+template<typename T, class V, class O>
+void QDeclarativeThread::postMethodToMain(void (O::*Member)(V), const T &arg)
+{
+ struct I : public Message {
+ void (O::*Member)(V);
+ T arg;
+ I(void (O::*Member)(V), const T &arg) : Member(Member), arg(arg) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg);
+ }
+ };
+ internalPostMethodToMain(new I(Member, arg));
+}
+
+template<typename T, typename T2, class V, class V2, class O>
+void QDeclarativeThread::postMethodToMain(void (O::*Member)(V, V2), const T &arg, const T2 &arg2)
+{
+ struct I : public Message {
+ void (O::*Member)(V, V2);
+ T arg;
+ T2 arg2;
+ I(void (O::*Member)(V, V2), const T &arg, const T2 &arg2) : Member(Member), arg(arg), arg2(arg2) {}
+ virtual void call(QDeclarativeThread *thread) {
+ O *me = static_cast<O *>(thread);
+ (me->*Member)(arg, arg2);
+ }
+ };
+ internalPostMethodToMain(new I(Member, arg, arg2));
+}
+
+QT_END_NAMESPACE
+
+#endif // QDECLARATIVETHREAD_P_H
diff --git a/src/declarative/qml/ftw/qfieldlist_p.h b/src/declarative/qml/ftw/qfieldlist_p.h
index ff6b89b96f..f0efd16a20 100644
--- a/src/declarative/qml/ftw/qfieldlist_p.h
+++ b/src/declarative/qml/ftw/qfieldlist_p.h
@@ -61,6 +61,8 @@ class QFieldList
public:
inline QFieldList();
inline N *first() const;
+ inline N *takeFirst();
+
inline void append(N *);
inline void prepend(N *);
@@ -73,6 +75,8 @@ public:
inline void prepend(QFieldList<N, nextMember> &);
inline void insertAfter(N *, QFieldList<N, nextMember> &);
+ inline void copyAndClear(QFieldList<N, nextMember> &);
+
static inline N *next(N *v);
private:
@@ -94,6 +98,21 @@ N *QFieldList<N, nextMember>::first() const
}
template<class N, N *N::*nextMember>
+N *QFieldList<N, nextMember>::takeFirst()
+{
+ N *value = _first;
+ if (value) {
+ _first = next(value);
+ if (_last == value) {
+ Q_ASSERT(_first == 0);
+ _last = 0;
+ }
+ --_count;
+ }
+ return value;
+}
+
+template<class N, N *N::*nextMember>
void QFieldList<N, nextMember>::append(N *v)
{
Q_ASSERT(v->*nextMember == 0);
@@ -207,4 +226,14 @@ void QFieldList<N, nextMember>::insertAfter(N *after, QFieldList<N, nextMember>
}
}
+template<class N, N *N::*nextMember>
+void QFieldList<N, nextMember>::copyAndClear(QFieldList<N, nextMember> &o)
+{
+ _first = o._first;
+ _last = o._last;
+ _count = o._count;
+ o._first = o._last = 0;
+ o._count = 0;
+}
+
#endif // QFIELDLIST_P_H
diff --git a/src/declarative/qml/ftw/qfinitestack_p.h b/src/declarative/qml/ftw/qfinitestack_p.h
new file mode 100644
index 0000000000..de9d833762
--- /dev/null
+++ b/src/declarative/qml/ftw/qfinitestack_p.h
@@ -0,0 +1,186 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the QtDeclarative module of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#ifndef QFINITESTACK_P_H
+#define QFINITESTACK_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#include <QtCore/qglobal.h>
+
+QT_BEGIN_NAMESPACE
+
+template<typename T>
+struct QFiniteStack {
+ inline QFiniteStack();
+ inline ~QFiniteStack();
+
+ inline void deallocate();
+ inline void allocate(int size);
+
+ inline bool isEmpty() const;
+ inline const T &top() const;
+ inline T &top();
+ inline void push(const T &o);
+ inline T pop();
+ inline int count() const;
+ inline const T &at(int index) const;
+ inline T &operator[](int index);
+private:
+ T *_array;
+ int _alloc;
+ int _size;
+};
+
+template<typename T>
+QFiniteStack<T>::QFiniteStack()
+: _array(0), _alloc(0), _size(0)
+{
+}
+
+template<typename T>
+QFiniteStack<T>::~QFiniteStack()
+{
+ deallocate();
+}
+
+template<typename T>
+bool QFiniteStack<T>::isEmpty() const
+{
+ return _size == 0;
+}
+
+template<typename T>
+const T &QFiniteStack<T>::top() const
+{
+ return _array[_size - 1];
+}
+
+template<typename T>
+T &QFiniteStack<T>::top()
+{
+ return _array[_size - 1];
+}
+
+template<typename T>
+void QFiniteStack<T>::push(const T &o)
+{
+ if (QTypeInfo<T>::isComplex) {
+ new (_array + _size++) T(o);
+ } else {
+ _array[_size++] = o;
+ }
+}
+
+template<typename T>
+T QFiniteStack<T>::pop()
+{
+ --_size;
+
+ if (QTypeInfo<T>::isComplex) {
+ T rv = _array[_size];
+ (_array + _size)->~T();
+ return rv;
+ } else {
+ return _array[_size];
+ }
+}
+
+template<typename T>
+int QFiniteStack<T>::count() const
+{
+ return _size;
+}
+
+template<typename T>
+const T &QFiniteStack<T>::at(int index) const
+{
+ return _array[index];
+}
+
+template<typename T>
+T &QFiniteStack<T>::operator[](int index)
+{
+ return _array[index];
+}
+
+template<typename T>
+void QFiniteStack<T>::allocate(int size)
+{
+ Q_ASSERT(_array == 0);
+ Q_ASSERT(_alloc == 0);
+ Q_ASSERT(_size == 0);
+
+ if (!size) return;
+
+ _array = (T *)qMalloc(size * sizeof(T));
+ _alloc = size;
+}
+
+template<typename T>
+void QFiniteStack<T>::deallocate()
+{
+ if (QTypeInfo<T>::isComplex) {
+ T *i = _array + _size;
+ while (i != _array)
+ (--i)->~T();
+ }
+
+ qFree(_array);
+
+ _array = 0;
+ _alloc = 0;
+ _size = 0;
+}
+
+QT_END_NAMESPACE
+
+#endif // QFINITESTACK_P_H
+