/****************************************************************************
**
-** Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
+** Copyright (C) 2012 Nokia Corporation and/or its subsidiary(-ies).
** All rights reserved.
-** Contact: Nokia Corporation (qt-info@nokia.com)
+** Contact: http://www.qt-project.org/
**
** This file is part of the QtDeclarative module of the Qt Toolkit.
**
//
#include <QtCore/qobject.h>
+#include <QtCore/qatomic.h>
#include <QtNetwork/qnetworkreply.h>
-#include <QtDeclarative/qjsvalue.h>
#include <QtDeclarative/qdeclarativeerror.h>
#include <QtDeclarative/qdeclarativeengine.h>
-#include <private/qdeclarativecleanup_p.h>
-#include <private/qdeclarativescript_p.h>
-#include <private/qdeclarativedirparser_p.h>
-#include <private/qdeclarativeimport_p.h>
-#include "private/qhashedstring_p.h"
#include <private/qv8_p.h>
+#include <private/qhashedstring_p.h>
+#include <private/qdeclarativescript_p.h>
+#include <private/qdeclarativeimport_p.h>
+#include <private/qdeclarativecleanup_p.h>
+#include <private/qdeclarativedirparser_p.h>
QT_BEGIN_NAMESPACE
class QDeclarativeComponentPrivate;
class QDeclarativeTypeData;
class QDeclarativeDataLoader;
+class QDeclarativeExtensionInterface;
// Exported for QtQuick1
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDataBlob : public QDeclarativeRefCount
QList<QDeclarativeError> errors() const;
+protected:
+ // Can be called from within callbacks
void setError(const QDeclarativeError &);
void setError(const QList<QDeclarativeError> &errors);
-
void addDependency(QDeclarativeDataBlob *);
-protected:
+ // Callbacks made in load thread
virtual void dataReceived(const QByteArray &) = 0;
-
virtual void done();
virtual void networkError(QNetworkReply::NetworkError);
-
virtual void dependencyError(QDeclarativeDataBlob *);
virtual void dependencyComplete(QDeclarativeDataBlob *);
virtual void allDependenciesDone();
-
- virtual void downloadProgressChanged(qreal);
+ // Callbacks made in main thread
+ virtual void downloadProgressChanged(qreal);
+ virtual void completed();
private:
friend class QDeclarativeDataLoader;
+ friend class QDeclarativeDataLoaderThread;
+
void tryDone();
void cancelAllWaitingFor();
void notifyAllWaitingOnMe();
void notifyComplete(QDeclarativeDataBlob *);
+ struct ThreadData {
+ inline ThreadData();
+ inline QDeclarativeDataBlob::Status status() const;
+ inline void setStatus(QDeclarativeDataBlob::Status);
+ inline bool isAsync() const;
+ inline void setIsAsync(bool);
+ inline quint8 progress() const;
+ inline void setProgress(quint8);
+
+ private:
+ QAtomicInt _p;
+ };
+ ThreadData m_data;
+
+ // m_errors should *always* be written before the status is set to Error.
+ // We use the status change as a memory fence around m_errors so that locking
+ // isn't required. Once the status is set to Error (or Complete), m_errors
+ // cannot be changed.
+ QList<QDeclarativeError> m_errors;
+
Type m_type;
- Status m_status;
- qreal m_progress;
QUrl m_url;
QUrl m_finalUrl;
int m_redirectCount:30;
bool m_inCallback:1;
bool m_isDone:1;
-
- QList<QDeclarativeError> m_errors;
};
+class QDeclarativeDataLoaderThread;
// Exported for QtQuick1
-class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDataLoader : public QObject
+class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeDataLoader
{
- Q_OBJECT
public:
QDeclarativeDataLoader(QDeclarativeEngine *);
~QDeclarativeDataLoader();
- void load(QDeclarativeDataBlob *);
- void loadWithStaticData(QDeclarativeDataBlob *, const QByteArray &);
+ void lock();
+ void unlock();
- QDeclarativeEngine *engine() const;
+ bool isConcurrent() const { return true; }
+
+ enum Mode { PreferSynchronous, Asynchronous };
-private slots:
- void networkReplyFinished();
- void networkReplyProgress(qint64,qint64);
+ void load(QDeclarativeDataBlob *, Mode = PreferSynchronous);
+ void loadWithStaticData(QDeclarativeDataBlob *, const QByteArray &, Mode = PreferSynchronous);
+
+ QDeclarativeEngine *engine() const;
+ void initializeEngine(QDeclarativeExtensionInterface *, const char *);
private:
+ friend class QDeclarativeDataBlob;
+ friend class QDeclarativeDataLoaderThread;
+ friend class QDeclarativeDataLoaderNetworkReplyProxy;
+
+ void loadThread(QDeclarativeDataBlob *);
+ void loadWithStaticDataThread(QDeclarativeDataBlob *, const QByteArray &);
+ void networkReplyFinished(QNetworkReply *);
+ void networkReplyProgress(QNetworkReply *, qint64, qint64);
+
+ typedef QHash<QNetworkReply *, QDeclarativeDataBlob *> NetworkReplies;
+
void setData(QDeclarativeDataBlob *, const QByteArray &);
QDeclarativeEngine *m_engine;
- typedef QHash<QNetworkReply *, QDeclarativeDataBlob *> NetworkReplies;
+ QDeclarativeDataLoaderThread *m_thread;
NetworkReplies m_networkReplies;
};
// Exported for QtQuick1
class Q_DECLARATIVE_PRIVATE_EXPORT QDeclarativeTypeLoader : public QDeclarativeDataLoader
{
- Q_OBJECT
+ Q_DECLARE_TR_FUNCTIONS(QDeclarativeTypeLoader)
public:
QDeclarativeTypeLoader(QDeclarativeEngine *);
~QDeclarativeTypeLoader();
QString absoluteFilePath(const QString &path);
bool directoryExists(const QString &path);
const QDeclarativeDirParser *qmlDirParser(const QString &absoluteFilePath);
-
private:
typedef QHash<QUrl, QDeclarativeTypeData *> TypeCache;
typedef QHash<QUrl, QDeclarativeScriptBlob *> ScriptCache;
protected:
virtual void done();
+ virtual void completed();
virtual void dataReceived(const QByteArray &);
virtual void allDependenciesDone();
virtual void downloadProgressChanged(qreal);
QDeclarativeTypeLoader *m_typeLoader;
};
-class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeRefCount, public QDeclarativeCleanup
+// QDeclarativeScriptData instances are created, uninitialized, by the loader in the
+// load thread. The first time they are used by the VME, they are initialized which
+// creates their v8 objects and they are referenced and added to the engine's cleanup
+// list. During QDeclarativeCleanup::clear() all v8 resources are destroyed, and the
+// reference that was created is released but final deletion only occurs once all the
+// references as released. This is all intended to ensure that the v8 resources are
+// only created and destroyed in the main thread :)
+class Q_AUTOTEST_EXPORT QDeclarativeScriptData : public QDeclarativeCleanup,
+ public QDeclarativeRefCount
{
public:
- QDeclarativeScriptData(QDeclarativeEngine *);
+ QDeclarativeScriptData();
~QDeclarativeScriptData();
QUrl url;
QList<QDeclarativeScriptBlob *> scripts;
QDeclarativeScript::Object::ScriptBlock::Pragmas pragmas;
+ bool isInitialized() const { return hasEngine(); }
+ void initialize(QDeclarativeEngine *);
+
protected:
virtual void clear(); // From QDeclarativeCleanup
friend class QDeclarativeScriptBlob;
bool m_loaded;
+ QString m_programSource;
v8::Persistent<v8::Script> m_program;
v8::Persistent<v8::Object> m_value;
-// QScriptProgram m_program;
-// QScriptValue m_value;
};
class Q_AUTOTEST_EXPORT QDeclarativeScriptBlob : public QDeclarativeDataBlob