Merge pull request #10657 from jherico/tablet_deadlock

Attempt to resolve Tablet scripting interface deadlocks
This commit is contained in:
Brad Davis 2017-06-12 17:06:58 -07:00 committed by GitHub
commit 308e7295cc

View file

@ -540,7 +540,7 @@ void TabletProxy::gotoWebScreen(const QString& url, const QString& injectedJavaS
QObject* TabletProxy::addButton(const QVariant& properties) { QObject* TabletProxy::addButton(const QVariant& properties) {
auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap())); auto tabletButtonProxy = QSharedPointer<TabletButtonProxy>(new TabletButtonProxy(properties.toMap()));
std::lock_guard<std::mutex> guard(_tabletMutex); std::unique_lock<std::mutex> guard(_tabletMutex);
_tabletButtonProxies.push_back(tabletButtonProxy); _tabletButtonProxies.push_back(tabletButtonProxy);
if (!_toolbarMode && _qmlTabletRoot) { if (!_toolbarMode && _qmlTabletRoot) {
auto tablet = getQmlTablet(); auto tablet = getQmlTablet();
@ -550,7 +550,6 @@ QObject* TabletProxy::addButton(const QVariant& properties) {
qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml";
} }
} else if (_toolbarMode) { } else if (_toolbarMode) {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>(); auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy(); QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy();
@ -559,6 +558,8 @@ QObject* TabletProxy::addButton(const QVariant& properties) {
connectionType = Qt::BlockingQueuedConnection; connectionType = Qt::BlockingQueuedConnection;
} }
guard.unlock();
// copy properties from tablet button proxy to toolbar button proxy. // copy properties from tablet button proxy to toolbar button proxy.
QObject* toolbarButtonProxy = nullptr; QObject* toolbarButtonProxy = nullptr;
bool hasResult = QMetaObject::invokeMethod(toolbarProxy, "addButton", connectionType, Q_RETURN_ARG(QObject*, toolbarButtonProxy), Q_ARG(QVariant, tabletButtonProxy->getProperties())); bool hasResult = QMetaObject::invokeMethod(toolbarProxy, "addButton", connectionType, Q_RETURN_ARG(QObject*, toolbarButtonProxy), Q_ARG(QVariant, tabletButtonProxy->getProperties()));
@ -576,31 +577,38 @@ bool TabletProxy::onHomeScreen() {
} }
void TabletProxy::removeButton(QObject* tabletButtonProxy) { void TabletProxy::removeButton(QObject* tabletButtonProxy) {
std::lock_guard<std::mutex> guard(_tabletMutex); std::unique_lock<std::mutex> guard(_tabletMutex);
auto tablet = getQmlTablet(); auto tablet = getQmlTablet();
if (!tablet) { if (!tablet) {
qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml"; qCCritical(scriptengine) << "Could not find tablet in TabletRoot.qml";
} }
auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy); QSharedPointer<TabletButtonProxy> buttonProxy;
if (iter != _tabletButtonProxies.end()) { {
if (!_toolbarMode && _qmlTabletRoot) { auto iter = std::find(_tabletButtonProxies.begin(), _tabletButtonProxies.end(), tabletButtonProxy);
(*iter)->setQmlButton(nullptr); if (iter == _tabletButtonProxies.end()) {
if (tablet) { qCWarning(scriptengine) << "TabletProxy::removeButton() could not find button " << tabletButtonProxy;
QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getProperties())); return;
}
} else if (_toolbarMode) {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy();
// remove button from toolbarProxy
QMetaObject::invokeMethod(toolbarProxy, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, (*iter)->getUuid().toString()));
(*iter)->setToolbarButtonProxy(nullptr);
} }
buttonProxy = *iter;
_tabletButtonProxies.erase(iter); _tabletButtonProxies.erase(iter);
} else { }
qCWarning(scriptengine) << "TabletProxy::removeButton() could not find button " << tabletButtonProxy;
if (!_toolbarMode && _qmlTabletRoot) {
buttonProxy->setQmlButton(nullptr);
if (tablet) {
guard.unlock();
QMetaObject::invokeMethod(tablet, "removeButtonProxy", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getProperties()));
}
} else if (_toolbarMode) {
auto tabletScriptingInterface = DependencyManager::get<TabletScriptingInterface>();
QObject* toolbarProxy = tabletScriptingInterface->getSystemToolbarProxy();
// remove button from toolbarProxy
guard.unlock();
QMetaObject::invokeMethod(toolbarProxy, "removeButton", Qt::AutoConnection, Q_ARG(QVariant, buttonProxy->getUuid().toString()));
buttonProxy->setToolbarButtonProxy(nullptr);
} }
} }