History

decouple initialization from storage in Table.getTablet()

Zach Pomerantz committed 9 years ago

Commit 03539401 parent 53021102 files · +48 −33Browse files

Showing the changes to libraries/script-engine/src/TabletScriptingInterface.cpp (1 of 2 files). Show all

Unified · Split

libraries/script-engine/src/TabletScriptingInterface.cpp+44−29
@@ -21,6 +21,8 @@ · 20 unmodified lines
2121 #include <InfoView.h>
2222 #include "SoundEffect.h"
2323
24+const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
25+const QString SYSTEM_TABLET = "com.highfidelity.interface.tablet.system";
2426
2527 QScriptValue tabletToScriptValue(QScriptEngine* engine, TabletProxy* const &in) {
2628 return engine->newQObject(in, QScriptEngine::QtOwnership, QScriptEngine::ExcludeDeleteLater | QScriptEngine::ExcludeChildObjects);
@@ -35,11 +37,11 @@ TabletScriptingInterface::TabletScriptingInterface() { · 8 unmodified lines
3537 }
3638
3739 QObject* TabletScriptingInterface::getSystemToolbarProxy() {
38− const QString SYSTEM_TOOLBAR = "com.highfidelity.interface.toolbar.system";
3940 Qt::ConnectionType connectionType = Qt::AutoConnection;
4041 if (QThread::currentThread() != _toolbarScriptingInterface->thread()) {
4142 connectionType = Qt::BlockingQueuedConnection;
4243 }
44+
4345 QObject* toolbarProxy = nullptr;
4446 bool hasResult = QMetaObject::invokeMethod(_toolbarScriptingInterface, "getToolbar", connectionType, Q_RETURN_ARG(QObject*, toolbarProxy), Q_ARG(QString, SYSTEM_TOOLBAR));
4547 if (hasResult) {
@@ -51,28 +53,38 @@ QObject* TabletScriptingInterface::getSystemToolbarProxy() { · 5 unmodified lines
5153 }
5254
5355 TabletProxy* TabletScriptingInterface::getTablet(const QString& tabletId) {
54−
55− std::lock_guard<std::mutex> guard(_mutex);
56−
57− // look up tabletId in the map.
58− auto iter = _tabletProxies.find(tabletId);
59− if (iter != _tabletProxies.end()) {
60− // tablet already exists, just return it.
61− return iter->second;
62− } else {
63− // allocate a new tablet, add it to the map then return it.
64− auto tabletProxy = new TabletProxy(tabletId);
65− tabletProxy->setParent(this);
66− _tabletProxies[tabletId] = tabletProxy;
67− tabletProxy->setToolbarMode(_toolbarMode);
68− return tabletProxy;
56+ TabletProxy* tabletProxy = nullptr;
57+ {
58+ // the only thing guarded should be map mutation
59+ // this avoids a deadlock with the Main thread
60+ // from Qt::BlockingQueuedEvent invocations later in the call-tree
61+ std::lock_guard<std::mutex> guard(_mapMutex);
62+
63+ auto iter = _tabletProxies.find(tabletId);
64+ if (iter != _tabletProxies.end()) {
65+ // tablet already exists
66+ return iter->second;
67+ } else {
68+ // tablet must be created
69+ tabletProxy = new TabletProxy(this, tabletId);
70+ _tabletProxies[tabletId] = tabletProxy;
71+ }
6972 }
73+
74+ assert(tabletProxy);
75+ // initialize new tablet
76+ tabletProxy->setToolbarMode(_toolbarMode);
77+ return tabletProxy;
7078 }
7179
7280 void TabletScriptingInterface::setToolbarMode(bool toolbarMode) {
73− std::lock_guard<std::mutex> guard(_mutex);
74−
75− _toolbarMode = toolbarMode;
81+ {
82+ // the only thing guarded should be _toolbarMode
83+ // this avoids a deadlock with the Main thread
84+ // from Qt::BlockingQueuedEvent invocations later in the call-tree
85+ std::lock_guard<std::mutex> guard(_mapMutex);
86+ _toolbarMode = toolbarMode;
87+ }
7688
7789 for (auto& iter : _tabletProxies) {
7890 iter.second->setToolbarMode(toolbarMode);
@@ -89,8 +101,9 @@ void TabletScriptingInterface::setQmlTabletRoot(QString tabletId, QQuickItem* qm · 10 unmodified lines
89101 }
90102
91103 QQuickWindow* TabletScriptingInterface::getTabletWindow() {
92− TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet("com.highfidelity.interface.tablet.system"));
104+ TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(SYSTEM_TABLET));
93105 QObject* qmlSurface = tablet->getTabletSurface();
106+
94107 OffscreenQmlSurface* surface = dynamic_cast<OffscreenQmlSurface*>(qmlSurface);
95108
96109 if (!surface) {
@@ -156,7 +169,7 @@ void TabletScriptingInterface::processTabletEvents(QObject* object, const QKeyEv · 59 unmodified lines
156169
157170
158171 void TabletScriptingInterface::processEvent(const QKeyEvent* event) {
159− TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet("com.highfidelity.interface.tablet.system"));
172+ TabletProxy* tablet = qobject_cast<TabletProxy*>(getTablet(SYSTEM_TABLET));
160173 QObject* qmlTablet = tablet->getQmlTablet();
161174 QObject* qmlMenu = tablet->getQmlMenu();
162175
@@ -185,10 +198,12 @@ class TabletRootWindow : public QmlWindowClass { · 22 unmodified lines
185198 virtual QString qmlSource() const override { return "hifi/tablet/WindowRoot.qml"; }
186199 };
187200
188−TabletProxy::TabletProxy(QString name) : _name(name) {
201+TabletProxy::TabletProxy(QObject* parent, QString name) : QObject(parent), _name(name) {
189202 }
190203
191204 void TabletProxy::setToolbarMode(bool toolbarMode) {
205+ std::lock_guard<std::mutex> guard(_tabletMutex);
206+
192207 if (toolbarMode == _toolbarMode) {
193208 return;
194209 }
@@ -288,7 +303,7 @@ bool TabletProxy::isPathLoaded(QVariant path) { · 93 unmodified lines
288303 return path.toString() == _currentPathLoaded.toString();
289304 }
290305 void TabletProxy::setQmlTabletRoot(QQuickItem* qmlTabletRoot, QObject* qmlOffscreenSurface) {
291− std::lock_guard<std::mutex> guard(_mutex);
306+ std::lock_guard<std::mutex> guard(_tabletMutex);
292307 _qmlOffscreenSurface = qmlOffscreenSurface;
293308 _qmlTabletRoot = qmlTabletRoot;
294309 if (_qmlTabletRoot && _qmlOffscreenSurface) {
@@ -519,7 +534,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS · 224 unmodified lines
519534
520535 QObject* TabletProxy::addButton(const QVariant& properties) {
521536 auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
522− std::lock_guard<std::mutex> guard(_mutex);
537+ std::lock_guard<std::mutex> guard(_tabletMutex);
523538 _tabletButtonProxies.push_back(tabletButtonProxy);
524539 if (!_toolbarMode && _qmlTabletRoot) {
525540 auto tablet = getQmlTablet();
@@ -555,7 +570,7 @@ bool TabletProxy::onHomeScreen() { · 29 unmodified lines
555570 }
556571
557572 void TabletProxy::removeButton(QObject* tabletButtonProxy) {
558− std::lock_guard<std::mutex> guard(_mutex);
573+ std::lock_guard<std::mutex> guard(_tabletMutex);
559574
560575 auto tablet = getQmlTablet();
561576 if (!tablet) {
@@ -743,12 +758,12 @@ TabletButtonProxy::TabletButtonProxy(const QVariantMap& properties) : · 181 unmodified lines
743758 }
744759
745760 void TabletButtonProxy::setQmlButton(QQuickItem* qmlButton) {
746− std::lock_guard<std::mutex> guard(_mutex);
761+ std::lock_guard<std::mutex> guard(_buttonMutex);
747762 _qmlButton = qmlButton;
748763 }
749764
750765 void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) {
751− std::lock_guard<std::mutex> guard(_mutex);
766+ std::lock_guard<std::mutex> guard(_buttonMutex);
752767 _toolbarButtonProxy = toolbarButtonProxy;
753768 if (_toolbarButtonProxy) {
754769 QObject::connect(_toolbarButtonProxy, SIGNAL(clicked()), this, SLOT(clickedSlot()));
@@ -756,12 +771,12 @@ void TabletButtonProxy::setToolbarButtonProxy(QObject* toolbarButtonProxy) { · 1 unmodified line
756771 }
757772
758773 QVariantMap TabletButtonProxy::getProperties() const {
759− std::lock_guard<std::mutex> guard(_mutex);
774+ std::lock_guard<std::mutex> guard(_buttonMutex);
760775 return _properties;
761776 }
762777
763778 void TabletButtonProxy::editProperties(QVariantMap properties) {
764− std::lock_guard<std::mutex> guard(_mutex);
779+ std::lock_guard<std::mutex> guard(_buttonMutex);
765780
766781 QVariantMap::const_iterator iter = properties.constBegin();
767782 while (iter != properties.constEnd()) {