From 4cc230ade4df3919fbb9688b60e6e8f7f3cc8144 Mon Sep 17 00:00:00 2001 From: Ulf Hermann Date: Thu, 6 Feb 2014 14:43:26 +0100 Subject: Unify initial waiting of debug services The debug services generally behave in one of two ways when initializing: Either they block the initializing thread until some configuration is passed over the network or they just go on. By introducing a generalized configurable debug service the various ways of waiting on initialization are cleaned up. The API defined for it also allows for engine-specific initialization. Change-Id: Id5685ef17d2a7eb1222629f7caa5ec53076d47b2 Reviewed-by: Kai Koehne --- src/qml/debugger/qqmldebugserver.cpp | 57 +++++++++++++++++++++++++++++++++--- 1 file changed, 53 insertions(+), 4 deletions(-) (limited to 'src/qml/debugger/qqmldebugserver.cpp') diff --git a/src/qml/debugger/qqmldebugserver.cpp b/src/qml/debugger/qqmldebugserver.cpp index f1e17df12b..a2bf19dee7 100644 --- a/src/qml/debugger/qqmldebugserver.cpp +++ b/src/qml/debugger/qqmldebugserver.cpp @@ -120,6 +120,22 @@ public: bool gotHello; bool blockingMode; + class EngineCondition { + public: + EngineCondition() : numServices(0), condition(new QWaitCondition) {} + + bool waitForServices(QReadWriteLock *locked, int numEngines); + + void wake(); + private: + int numServices; + + // shared pointer to allow for QHash-inflicted copying. + QSharedPointer condition; + }; + + QHash engineConditions; + QMutex helloMutex; QWaitCondition helloCondition; QQmlDebugServerThread *thread; @@ -573,12 +589,12 @@ QStringList QQmlDebugServer::serviceNames() const void QQmlDebugServer::addEngine(QQmlEngine *engine) { Q_D(QQmlDebugServer); - QReadLocker lock(&d->pluginsLock); + QWriteLocker lock(&d->pluginsLock); foreach (QQmlDebugService *service, d->plugins) service->engineAboutToBeAdded(engine); - // TODO: Later wait here for initialization. + d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count()); foreach (QQmlDebugService *service, d->plugins) service->engineAdded(engine); @@ -587,12 +603,12 @@ void QQmlDebugServer::addEngine(QQmlEngine *engine) void QQmlDebugServer::removeEngine(QQmlEngine *engine) { Q_D(QQmlDebugServer); - QReadLocker lock(&d->pluginsLock); + QWriteLocker lock(&d->pluginsLock); foreach (QQmlDebugService *service, d->plugins) service->engineAboutToBeRemoved(engine); - // TODO: Later wait here for cleanup + d->engineConditions[engine].waitForServices(&d->pluginsLock, d->plugins.count()); foreach (QQmlDebugService *service, d->plugins) service->engineRemoved(engine); @@ -605,6 +621,12 @@ bool QQmlDebugServer::addService(QQmlDebugService *service) // to be executed outside of debugger thread Q_ASSERT(QThread::currentThread() != thread()); + connect(service, SIGNAL(attachedToEngine(QQmlEngine*)), + this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection); + connect(service, SIGNAL(detachedFromEngine(QQmlEngine*)), + this, SLOT(wakeEngine(QQmlEngine*)), Qt::QueuedConnection); + + QWriteLocker lock(&d->pluginsLock); if (!service || d->plugins.contains(service->name())) return false; @@ -656,6 +678,33 @@ void QQmlDebugServer::sendMessages(QQmlDebugService *service, Q_ARG(QList, prefixedMessages)); } +void QQmlDebugServer::wakeEngine(QQmlEngine *engine) +{ + // to be executed in debugger thread + Q_ASSERT(QThread::currentThread() == thread()); + + Q_D(QQmlDebugServer); + QWriteLocker lock(&d->pluginsLock); + d->engineConditions[engine].wake(); +} + +bool QQmlDebugServerPrivate::EngineCondition::waitForServices(QReadWriteLock *locked, int num) +{ + // to be executed outside of debugger thread + Q_ASSERT(QThread::currentThread() != QQmlDebugServer::instance()->thread()); + + Q_ASSERT_X(numServices == 0, Q_FUNC_INFO, "Request to wait again before previous wait finished"); + numServices = num; + return condition->wait(locked); +} + +void QQmlDebugServerPrivate::EngineCondition::wake() +{ + if (--numServices == 0) + condition->wakeAll(); + Q_ASSERT_X(numServices >=0, Q_FUNC_INFO, "Woken more often than #services."); +} + QT_END_NAMESPACE #include "moc_qqmldebugserver_p.cpp" -- cgit v1.2.3