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 QString uiLanguage;
111
112 // These methods may be called from the QML loader thread
113 inline QQmlPropertyCache *cache(QObject *obj, int minorVersion = -1, bool doRef = false);
114 inline QQmlPropertyCache *cache(const QMetaObject *, int minorVersion = -1, bool doRef = false);
115};
116
117QJSEnginePrivate::Locker::Locker(const QJSEngine *e)
118: m_ep(QJSEnginePrivate::get(e))
119{
120 relock();
121}
122
123QJSEnginePrivate::Locker::Locker(const QJSEnginePrivate *e)
124: m_ep(e), m_locked(false)
125{
126 relock();
127}
128
129QJSEnginePrivate::Locker::~Locker()
130{
131 unlock();
132}
133
134void QJSEnginePrivate::Locker::unlock()
135{
136 if (m_locked) {
137 m_ep->mutex.unlock();
138 m_locked = false;
139 }
140}
141
142void QJSEnginePrivate::Locker::relock()
143{
144 Q_ASSERT(!m_locked);
145 m_ep->mutex.lock();
146 m_locked = true;
147}
148
149/*!
150Returns a QQmlPropertyCache for \a obj if one is available.
151
152If \a obj is null, being deleted or contains a dynamic meta object 0
153is returned.
154
155The returned cache is not referenced, so if it is to be stored, call addref().
156
157XXX thread There is a potential future race condition in this and all the cache()
158functions. As the QQmlPropertyCache is returned unreferenced, when called
159from the loader thread, it is possible that the cache will have been dereferenced
160and deleted before the loader thread has a chance to use or reference it. This
161can't currently happen as the cache holds a reference to the
162QQmlPropertyCache until the QQmlEngine is destroyed.
163*/
164QQmlPropertyCache *QJSEnginePrivate::cache(QObject *obj, int minorVersion, bool doRef)
165{
166 if (!obj || QObjectPrivate::get(o: obj)->metaObject || QObjectPrivate::get(o: obj)->wasDeleted)
167 return nullptr;
168
169 Locker locker(this);
170 const QMetaObject *mo = obj->metaObject();
171 return QQmlMetaType::propertyCache(metaObject: mo, minorVersion, doRef);
172}
173
174/*!
175Returns a QQmlPropertyCache for \a metaObject.
176
177As the cache is persisted for the life of the engine, \a metaObject must be
178a static "compile time" meta-object, or a meta-object that is otherwise known to
179exist for the lifetime of the QQmlEngine.
180
181The returned cache is not referenced, so if it is to be stored, call addref().
182*/
183QQmlPropertyCache *QJSEnginePrivate::cache(const QMetaObject *metaObject, int minorVersion, bool doRef)
184{
185 Q_ASSERT(metaObject);
186
187 Locker locker(this);
188 return QQmlMetaType::propertyCache(metaObject, minorVersion, doRef);
189}
190
191
192QT_END_NAMESPACE
193
194#endif // QJSENGINE_P_H
195

source code of qtdeclarative/src/qml/jsapi/qjsengine_p.h