aboutsummaryrefslogtreecommitdiffstats
path: root/src/qml/qml/qqmlengine_p.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/qml/qml/qqmlengine_p.h')
-rw-r--r--src/qml/qml/qqmlengine_p.h522
1 files changed, 522 insertions, 0 deletions
diff --git a/src/qml/qml/qqmlengine_p.h b/src/qml/qml/qqmlengine_p.h
new file mode 100644
index 0000000000..db834489ba
--- /dev/null
+++ b/src/qml/qml/qqmlengine_p.h
@@ -0,0 +1,522 @@
+/****************************************************************************
+**
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
+** Contact: http://www.qt-project.org/
+**
+** This file is part of the QtQml 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 QQMLENGINE_P_H
+#define QQMLENGINE_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 "qqmlengine.h"
+
+#include "qqmltypeloader_p.h"
+#include "qqmlimport_p.h"
+#include <private/qpodvector_p.h>
+#include "qqml.h"
+#include "qqmlvaluetype_p.h"
+#include "qqmlcontext.h"
+#include "qqmlcontext_p.h"
+#include "qqmlexpression.h"
+#include "qqmlimageprovider.h"
+#include "qqmlproperty_p.h"
+#include "qqmlpropertycache_p.h"
+#include "qqmlmetatype_p.h"
+#include "qqmldirparser_p.h"
+#include <private/qintrusivelist_p.h>
+#include <private/qrecyclepool_p.h>
+
+#include <QtCore/qlist.h>
+#include <QtCore/qpair.h>
+#include <QtCore/qstack.h>
+#include <QtCore/qmutex.h>
+#include <QtCore/qstring.h>
+#include <QtCore/qthread.h>
+
+#include <private/qobject_p.h>
+
+#include <private/qv8engine_p.h>
+#include <private/qjsengine_p.h>
+
+QT_BEGIN_NAMESPACE
+
+class QQmlContext;
+class QQmlEngine;
+class QQmlContextPrivate;
+class QQmlExpression;
+class QQmlImportDatabase;
+class QNetworkReply;
+class QNetworkAccessManager;
+class QQmlNetworkAccessManagerFactory;
+class QQmlAbstractBinding;
+class QQmlTypeNameCache;
+class QQmlComponentAttached;
+class QQmlCleanup;
+class QQmlDelayedError;
+class QQuickWorkerScriptEngine;
+class QQmlVME;
+class QDir;
+class QQmlIncubator;
+
+// This needs to be declared here so that the pool for it can live in QQmlEnginePrivate.
+// The inline method definitions are in qqmlexpression_p.h
+class QQmlJavaScriptExpressionGuard : public QQmlNotifierEndpoint
+{
+public:
+ inline QQmlJavaScriptExpressionGuard(QQmlJavaScriptExpression *);
+
+ static inline void endpointCallback(QQmlNotifierEndpoint *);
+ static inline QQmlJavaScriptExpressionGuard *New(QQmlJavaScriptExpression *e,
+ QQmlEngine *engine);
+ inline void Delete();
+
+ QQmlJavaScriptExpression *expression;
+ QQmlJavaScriptExpressionGuard *next;
+};
+
+class Q_QML_EXPORT QQmlEnginePrivate : public QJSEnginePrivate
+{
+ Q_DECLARE_PUBLIC(QQmlEngine)
+public:
+ QQmlEnginePrivate(QQmlEngine *);
+ ~QQmlEnginePrivate();
+
+ void init();
+
+ class PropertyCapture {
+ public:
+ inline virtual ~PropertyCapture() {}
+ virtual void captureProperty(QQmlNotifier *) = 0;
+ virtual void captureProperty(QObject *, int, int) = 0;
+ };
+
+ PropertyCapture *propertyCapture;
+ inline void captureProperty(QQmlNotifier *);
+ inline void captureProperty(QObject *, int, int);
+
+ QRecyclePool<QQmlJavaScriptExpressionGuard> jsExpressionGuardPool;
+
+ QQmlContext *rootContext;
+ bool isDebugging;
+
+ bool outputWarningsToStdErr;
+
+ QQmlContextData *sharedContext;
+ QObject *sharedScope;
+
+ // Registered cleanup handlers
+ QQmlCleanup *cleanup;
+
+ // Bindings that have had errors during startup
+ QQmlDelayedError *erroredBindings;
+ int inProgressCreations;
+
+ QV8Engine *v8engine() const { return q_func()->handle(); }
+
+ QQuickWorkerScriptEngine *getWorkerScriptEngine();
+ QQuickWorkerScriptEngine *workerScriptEngine;
+
+ QUrl baseUrl;
+
+ typedef QPair<QQmlGuard<QObject>,int> FinalizeCallback;
+ void registerFinalizeCallback(QObject *obj, int index);
+
+ QQmlVME *activeVME;
+
+ QNetworkAccessManager *createNetworkAccessManager(QObject *parent) const;
+ QNetworkAccessManager *getNetworkAccessManager() const;
+ mutable QNetworkAccessManager *networkAccessManager;
+ mutable QQmlNetworkAccessManagerFactory *networkAccessManagerFactory;
+
+ QHash<QString,QSharedPointer<QQmlImageProvider> > imageProviders;
+ QQmlImageProvider::ImageType getImageProviderType(const QUrl &url);
+ QQuickTextureFactory *getTextureFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
+ QImage getImageFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
+ QPixmap getPixmapFromProvider(const QUrl &url, QSize *size, const QSize& req_size);
+
+ // Scarce resources are "exceptionally high cost" QVariant types where allowing the
+ // normal JavaScript GC to clean them up is likely to lead to out-of-memory or other
+ // out-of-resource situations. When such a resource is passed into JavaScript we
+ // add it to the scarceResources list and it is destroyed when we return from the
+ // JavaScript execution that created it. The user can prevent this behavior by
+ // calling preserve() on the object which removes it from this scarceResource list.
+ class ScarceResourceData {
+ public:
+ ScarceResourceData(const QVariant &data) : data(data) {}
+ QVariant data;
+ QIntrusiveListNode node;
+ };
+ QIntrusiveList<ScarceResourceData, &ScarceResourceData::node> scarceResources;
+ int scarceResourcesRefCount;
+ void referenceScarceResources();
+ void dereferenceScarceResources();
+
+ QQmlTypeLoader typeLoader;
+ QQmlImportDatabase importDatabase;
+
+ QString offlineStoragePath;
+
+ mutable quint32 uniqueId;
+ inline quint32 getUniqueId() const {
+ return uniqueId++;
+ }
+
+ QQmlValueTypeFactory valueTypes;
+
+ // Unfortunate workaround to avoid a circular dependency between
+ // qqmlengine_p.h and qqmlincubator_p.h
+ struct Incubator {
+ QIntrusiveListNode next;
+ // Unfortunate workaround for MSVC
+ QIntrusiveListNode nextWaitingFor;
+ };
+ QIntrusiveList<Incubator, &Incubator::next> incubatorList;
+ unsigned int incubatorCount;
+ QQmlIncubationController *incubationController;
+ void incubate(QQmlIncubator &, QQmlContextData *);
+
+ // These methods may be called from any thread
+ inline bool isEngineThread() const;
+ inline static bool isEngineThread(const QQmlEngine *);
+ template<typename T>
+ inline void deleteInEngineThread(T *);
+ template<typename T>
+ inline static void deleteInEngineThread(QQmlEngine *, T *);
+
+ // These methods may be called from the loader thread
+ QQmlMetaType::ModuleApiInstance *moduleApiInstance(const QQmlMetaType::ModuleApi &module);
+
+ // These methods may be called from the loader thread
+ inline QQmlPropertyCache *cache(QObject *obj);
+ inline QQmlPropertyCache *cache(const QMetaObject *);
+ inline QQmlPropertyCache *cache(QQmlType *, int, QQmlError &error);
+
+ // These methods may be called from the loader thread
+ bool isQObject(int);
+ QObject *toQObject(const QVariant &, bool *ok = 0) const;
+ QQmlMetaType::TypeCategory typeCategory(int) const;
+ bool isList(int) const;
+ int listType(int) const;
+ const QMetaObject *rawMetaObjectForType(int) const;
+ const QMetaObject *metaObjectForType(int) const;
+ void registerCompositeType(QQmlCompiledData *);
+
+ void sendQuit();
+ void warning(const QQmlError &);
+ void warning(const QList<QQmlError> &);
+ static void warning(QQmlEngine *, const QQmlError &);
+ static void warning(QQmlEngine *, const QList<QQmlError> &);
+ static void warning(QQmlEnginePrivate *, const QQmlError &);
+ static void warning(QQmlEnginePrivate *, const QList<QQmlError> &);
+
+ inline static QV8Engine *getV8Engine(QQmlEngine *e);
+ inline static QQmlEnginePrivate *get(QQmlEngine *e);
+ inline static const QQmlEnginePrivate *get(const QQmlEngine *e);
+ inline static QQmlEnginePrivate *get(QQmlContext *c);
+ inline static QQmlEnginePrivate *get(QQmlContextData *c);
+ inline static QQmlEngine *get(QQmlEnginePrivate *p);
+
+ static QString urlToLocalFileOrQrc(const QUrl& url);
+ static QString urlToLocalFileOrQrc(const QString& url);
+
+ static void registerBaseTypes(const char *uri, int versionMajor, int versionMinor);
+ static void defineModule();
+
+ static bool qml_debugging_enabled;
+
+ mutable QMutex mutex;
+
+private:
+ // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
+ // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
+ // either idle, or is running with the main thread blocked, no locking is necessary. This way
+ // we only pay for locking when we have to.
+ // Consequently, this class should only be used to protect simple accesses or modifications of the
+ // QQmlEnginePrivate structures or operations that can be guarenteed not to start activity
+ // on the loader thread.
+ // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
+ // QMutex instance and multiple Lockers are recursive in the same thread.
+ class Locker
+ {
+ public:
+ inline Locker(const QQmlEngine *);
+ inline Locker(const QQmlEnginePrivate *);
+ inline ~Locker();
+
+ inline void unlock();
+ inline void relock();
+
+ private:
+ const QQmlEnginePrivate *m_ep;
+ quint32 m_locked:1;
+ };
+
+ // Must be called locked
+ QQmlPropertyCache *createCache(const QMetaObject *);
+ QQmlPropertyCache *createCache(QQmlType *, int, QQmlError &error);
+
+ // These members must be protected by a QQmlEnginePrivate::Locker as they are required by
+ // the threaded loader. Only access them through their respective accessor methods.
+ QHash<QQmlMetaType::ModuleApi, QQmlMetaType::ModuleApiInstance *> moduleApiInstances;
+ QHash<const QMetaObject *, QQmlPropertyCache *> propertyCache;
+ QHash<QPair<QQmlType *, int>, QQmlPropertyCache *> typePropertyCache;
+ QHash<int, int> m_qmlLists;
+ QHash<int, QQmlCompiledData *> m_compositeTypes;
+
+ // These members is protected by the full QQmlEnginePrivate::mutex mutex
+ struct Deletable { Deletable():next(0) {} virtual ~Deletable() {} Deletable *next; };
+ QFieldList<Deletable, &Deletable::next> toDeleteInEngineThread;
+ void doDeleteInEngineThread();
+};
+
+QQmlEnginePrivate::Locker::Locker(const QQmlEngine *e)
+: m_ep(QQmlEnginePrivate::get(e))
+{
+ relock();
+}
+
+QQmlEnginePrivate::Locker::Locker(const QQmlEnginePrivate *e)
+: m_ep(e), m_locked(false)
+{
+ relock();
+}
+
+QQmlEnginePrivate::Locker::~Locker()
+{
+ unlock();
+}
+
+void QQmlEnginePrivate::Locker::unlock()
+{
+ if (m_locked) {
+ m_ep->mutex.unlock();
+ m_locked = false;
+ }
+}
+
+void QQmlEnginePrivate::Locker::relock()
+{
+ Q_ASSERT(!m_locked);
+ if (m_ep->typeLoader.isConcurrent()) {
+ m_ep->mutex.lock();
+ m_locked = true;
+ }
+}
+
+/*!
+Returns true if the calling thread is the QQmlEngine thread.
+*/
+bool QQmlEnginePrivate::isEngineThread() const
+{
+ Q_Q(const QQmlEngine);
+ return QThread::currentThread() == q->thread();
+}
+
+/*!
+Returns true if the calling thread is the QQmlEngine \a engine thread.
+*/
+bool QQmlEnginePrivate::isEngineThread(const QQmlEngine *engine)
+{
+ Q_ASSERT(engine);
+ return QQmlEnginePrivate::get(engine)->isEngineThread();
+}
+
+/*!
+Delete \a value in the engine thread. If the calling thread is the engine
+thread, \a value will be deleted immediately.
+
+This method should be used for *any* type that has resources that need to
+be freed in the engine thread. This is generally types that use V8 handles.
+As there is some small overhead in checking the current thread, it is best
+practice to check if any V8 handles actually need to be freed and delete
+the instance directly if not.
+*/
+template<typename T>
+void QQmlEnginePrivate::deleteInEngineThread(T *value)
+{
+ Q_Q(QQmlEngine);
+
+ Q_ASSERT(value);
+ if (isEngineThread()) {
+ delete value;
+ } else {
+ struct I : public Deletable {
+ I(T *value) : value(value) {}
+ ~I() { delete value; }
+ T *value;
+ };
+ I *i = new I(value);
+ mutex.lock();
+ bool wasEmpty = toDeleteInEngineThread.isEmpty();
+ toDeleteInEngineThread.append(i);
+ mutex.unlock();
+ if (wasEmpty)
+ QCoreApplication::postEvent(q, new QEvent(QEvent::User));
+ }
+}
+
+/*!
+Delete \a value in the \a engine thread. If the calling thread is the engine
+thread, \a value will be deleted immediately.
+*/
+template<typename T>
+void QQmlEnginePrivate::deleteInEngineThread(QQmlEngine *engine, T *value)
+{
+ Q_ASSERT(engine);
+ QQmlEnginePrivate::get(engine)->deleteInEngineThread<T>(value);
+}
+
+/*!
+Returns a QQmlPropertyCache for \a obj if one is available.
+
+If \a obj is null, being deleted or contains a dynamic meta object 0
+is returned.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+
+XXX thread There is a potential future race condition in this and all the cache()
+functions. As the QQmlPropertyCache is returned unreferenced, when called
+from the loader thread, it is possible that the cache will have been dereferenced
+and deleted before the loader thread has a chance to use or reference it. This
+can't currently happen as the cache holds a reference to the
+QQmlPropertyCache until the QQmlEngine is destroyed.
+*/
+QQmlPropertyCache *QQmlEnginePrivate::cache(QObject *obj)
+{
+ if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
+ return 0;
+
+ Locker locker(this);
+ const QMetaObject *mo = obj->metaObject();
+ QQmlPropertyCache *rv = propertyCache.value(mo);
+ if (!rv) rv = createCache(mo);
+ return rv;
+}
+
+/*!
+Returns a QQmlPropertyCache for \a metaObject.
+
+As the cache is persisted for the life of the engine, \a metaObject must be
+a static "compile time" meta-object, or a meta-object that is otherwise known to
+exist for the lifetime of the QQmlEngine.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+*/
+QQmlPropertyCache *QQmlEnginePrivate::cache(const QMetaObject *metaObject)
+{
+ Q_ASSERT(metaObject);
+
+ Locker locker(this);
+ QQmlPropertyCache *rv = propertyCache.value(metaObject);
+ if (!rv) rv = createCache(metaObject);
+ return rv;
+}
+
+/*!
+Returns a QQmlPropertyCache for \a type with \a minorVersion.
+
+The returned cache is not referenced, so if it is to be stored, call addref().
+*/
+QQmlPropertyCache *QQmlEnginePrivate::cache(QQmlType *type, int minorVersion, QQmlError &error)
+{
+ Q_ASSERT(type);
+
+ if (minorVersion == -1 || !type->containsRevisionedAttributes())
+ return cache(type->metaObject());
+
+ Locker locker(this);
+ QQmlPropertyCache *rv = typePropertyCache.value(qMakePair(type, minorVersion));
+ if (!rv) rv = createCache(type, minorVersion, error);
+ return rv;
+}
+
+QV8Engine *QQmlEnginePrivate::getV8Engine(QQmlEngine *e)
+{
+ return e->d_func()->v8engine();
+}
+
+QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlEngine *e)
+{
+ return e->d_func();
+}
+
+const QQmlEnginePrivate *QQmlEnginePrivate::get(const QQmlEngine *e)
+{
+ return e->d_func();
+}
+
+QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContext *c)
+{
+ return (c && c->engine()) ? QQmlEnginePrivate::get(c->engine()) : 0;
+}
+
+QQmlEnginePrivate *QQmlEnginePrivate::get(QQmlContextData *c)
+{
+ return (c && c->engine) ? QQmlEnginePrivate::get(c->engine) : 0;
+}
+
+QQmlEngine *QQmlEnginePrivate::get(QQmlEnginePrivate *p)
+{
+ return p->q_func();
+}
+
+void QQmlEnginePrivate::captureProperty(QQmlNotifier *n)
+{
+ if (propertyCapture)
+ propertyCapture->captureProperty(n);
+}
+
+void QQmlEnginePrivate::captureProperty(QObject *o, int c, int n)
+{
+ if (propertyCapture)
+ propertyCapture->captureProperty(o, c, n);
+}
+
+QT_END_NAMESPACE
+
+#endif // QQMLENGINE_P_H