1/****************************************************************************
2**
3** Copyright (C) 2016 The Qt Company Ltd.
4** Contact: https://www.qt.io/licensing/
5**
6** This file is part of the QtQml module of the Qt Toolkit.
7**
8** $QT_BEGIN_LICENSE:LGPL$
9** Commercial License Usage
10** Licensees holding valid commercial Qt licenses may use this file in
11** accordance with the commercial license agreement provided with the
12** Software or, alternatively, in accordance with the terms contained in
13** a written agreement between you and The Qt Company. For licensing terms
14** and conditions see https://www.qt.io/terms-conditions. For further
15** information use the contact form at https://www.qt.io/contact-us.
16**
17** GNU Lesser General Public License Usage
18** Alternatively, this file may be used under the terms of the GNU Lesser
19** General Public License version 3 as published by the Free Software
20** Foundation and appearing in the file LICENSE.LGPL3 included in the
21** packaging of this file. Please review the following information to
22** ensure the GNU Lesser General Public License version 3 requirements
23** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
24**
25** GNU General Public License Usage
26** Alternatively, this file may be used under the terms of the GNU
27** General Public License version 2.0 or (at your option) the GNU General
28** Public license version 3 or any later version approved by the KDE Free
29** Qt Foundation. The licenses are as published by the Free Software
30** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
31** included in the packaging of this file. Please review the following
32** information to ensure the GNU General Public License requirements will
33** be met: https://www.gnu.org/licenses/gpl-2.0.html and
34** https://www.gnu.org/licenses/gpl-3.0.html.
35**
36** $QT_END_LICENSE$
37**
38****************************************************************************/
39
40#ifndef QJSENGINE_P_H
41#define QJSENGINE_P_H
42
43//
44// W A R N I N G
45// -------------
46//
47// This file is not part of the Qt API. It exists purely as an
48// implementation detail. This header file may change from version to
49// version without notice, or even be removed.
50//
51// We mean it.
52//
53
54#include <QtCore/private/qobject_p.h>
55#include <QtCore/qmutex.h>
56#include "qjsengine.h"
57#include "private/qtqmlglobal_p.h"
58#include <private/qqmlmetatype_p.h>
59
60QT_BEGIN_NAMESPACE
61
62class QQmlPropertyCache;
63
64namespace QV4 {
65struct ExecutionEngine;
66}
67
68class Q_QML_PRIVATE_EXPORT QJSEnginePrivate : public QObjectPrivate
69{
70 Q_DECLARE_PUBLIC(QJSEngine)
71
72public:
73 static QJSEnginePrivate* get(QJSEngine*e) { return e->d_func(); }
74 static const QJSEnginePrivate* get(const QJSEngine*e) { return e->d_func(); }
75 static QJSEnginePrivate* get(QV4::ExecutionEngine *e);
76
77 QJSEnginePrivate() = default;
78 ~QJSEnginePrivate() override;
79
80 static void addToDebugServer(QJSEngine *q);
81 static void removeFromDebugServer(QJSEngine *q);
82
83 // Locker locks the QQmlEnginePrivate data structures for read and write, if necessary.
84 // Currently, locking is only necessary if the threaded loader is running concurrently. If it is
85 // either idle, or is running with the main thread blocked, no locking is necessary. This way
86 // we only pay for locking when we have to.
87 // Consequently, this class should only be used to protect simple accesses or modifications of the
88 // QQmlEnginePrivate structures or operations that can be guaranteed not to start activity
89 // on the loader thread.
90 // The Locker API is identical to QMutexLocker. Locker reuses the QQmlEnginePrivate::mutex
91 // QMutex instance and multiple Lockers are recursive in the same thread.
92 class Locker
93 {
94 public:
95 inline Locker(const QJSEngine *);
96 inline Locker(const QJSEnginePrivate *);
97 inline ~Locker();
98
99 inline void unlock();
100 inline void relock();
101
102 private:
103 const QJSEnginePrivate *m_ep;
104 quint32 m_locked:1;
105 };
106
107 // Shared by QQmlEngine
108 mutable QRecursiveMutex mutex;
109
110
111 // These methods may be called from the QML loader thread
112 inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1);
113 inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1);
114};
115
116QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
117: m_ep(QJSEnginePrivate::get(e))
118{
119 relock();
120}
121
122QJSEnginePrivate::Locker::Locker(const QJSEnginePrivate *e)
123: m_ep(e), m_locked(false)
124{
125 relock();
126}
127
128QJSEnginePrivate::Locker::~Locker()
129{
130 unlock();
131}
132
133void QJSEnginePrivate::Locker::unlock()
134{
135 if (m_locked) {
136 m_ep->mutex.unlock();
137 m_locked = false;
138 }
139}
140
141void QJSEnginePrivate::Locker::relock()
142{
143 Q_ASSERT(!m_locked);
144 m_ep->mutex.lock();
145 m_locked = true;
146}
147
148/*!
149Returns a QQmlPropertyCache for \a obj if one is available.
150
151If \a obj is null, being deleted or contains a dynamic meta object 0
152is returned.
153
154The returned cache is not referenced, so if it is to be stored, call addref().
155
156XXX thread There is a potential future race condition in this and all the cache()
157functions. As the QQmlPropertyCache is returned unreferenced, when called
158from the loader thread, it is possible that the cache will have been dereferenced
159and deleted before the loader thread has a chance to use or reference it. This
160can't currently happen as the cache holds a reference to the
161QQmlPropertyCache until the QQmlEngine is destroyed.
162*/
163QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion)
164{
165 if (!obj || QObjectPrivate::get(obj)->metaObject || QObjectPrivate::get(obj)->wasDeleted)
166 return nullptr;
167
168 Locker locker(this);
169 const QMetaObject *mo = obj->metaObject();
170 return QQmlMetaType::propertyCache(mo, minorVersion);
171}
172
173/*!
174Returns a QQmlPropertyCache for \a metaObject.
175
176As the cache is persisted for the life of the engine, \a metaObject must be
177a static "compile time" meta-object, or a meta-object that is otherwise known to
178exist for the lifetime of the QQmlEngine.
179
180The returned cache is not referenced, so if it is to be stored, call addref().
181*/
182QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion)
183{
184 Q_ASSERT(metaObject);
185
186 Locker locker(this);
187 return QQmlMetaType::propertyCache(metaObject, minorVersion);
188}
189
190
191QT_END_NAMESPACE
192
193#endif // QJSENGINE_P_H
194