summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorPaul Lemire <paul.lemire@kdab.com>2019-05-27 11:49:33 +0200
committerPaul Lemire <paul.lemire@kdab.com>2019-08-07 08:51:10 +0200
commit8daa8bcb8e9a7110289d15c94f53a4be9adac1ac (patch)
tree56330947d547e59efd9b08182a51589d82be5049
parentfd64e870fad0e619704e79689f20645760dbdc0e (diff)
Remove the Aspect Thread
This now makes the Qt3D simulation loop run in the Main Thread. In theory having the Aspect Thread allowed Qt3D to continue rendering even if the main thread got locked. In practice however this leads to a large amount of complexities in the Qt3D implementations and provides little value as in most cases blocking the main thread would block animations driven by frontend nodes. Removing the Aspect Thread will allow to remove the backend tree copies each aspect had to make which will allow to reduce memory. In addition, getting direct access to frontend nodes, will now be possible without introducing races which should allow to make more optimizations and reduce latencies on some operations. Change-Id: I80e4cd6427de06ddedfa1bb50d40710b91867b24 Reviewed-by: Mike Krus <mike.krus@kdab.com>
-rw-r--r--src/core/aspects/aspects.pri6
-rw-r--r--src/core/aspects/qaspectengine.cpp45
-rw-r--r--src/core/aspects/qaspectengine_p.h4
-rw-r--r--src/core/aspects/qaspectmanager.cpp265
-rw-r--r--src/core/aspects/qaspectmanager_p.h16
-rw-r--r--src/core/aspects/qaspectthread.cpp99
-rw-r--r--src/core/aspects/qaspectthread_p.h88
-rw-r--r--src/core/qchangearbiter_p.h4
-rw-r--r--src/core/services/qdownloadhelperservice.cpp4
-rw-r--r--src/input/backend/eventsourcesetterhelper.cpp25
-rw-r--r--src/input/backend/eventsourcesetterhelper_p.h6
-rw-r--r--src/input/backend/inputhandler.cpp20
-rw-r--r--src/input/backend/mousedevice.cpp1
-rw-r--r--src/logic/executor.cpp6
-rw-r--r--src/logic/executor_p.h2
-rw-r--r--src/logic/manager.cpp6
-rw-r--r--src/logic/manager_p.h1
-rw-r--r--tests/benchmarks/render/jobs/tst_bench_jobs.cpp1
18 files changed, 177 insertions, 422 deletions
diff --git a/src/core/aspects/aspects.pri b/src/core/aspects/aspects.pri
index ced33f310..5e8327192 100644
--- a/src/core/aspects/aspects.pri
+++ b/src/core/aspects/aspects.pri
@@ -4,8 +4,7 @@ SOURCES += \
$$PWD/qabstractaspect.cpp \
$$PWD/qaspectengine.cpp \
$$PWD/qaspectfactory.cpp \
- $$PWD/qaspectmanager.cpp \
- $$PWD/qaspectthread.cpp
+ $$PWD/qaspectmanager.cpp
HEADERS += \
$$PWD/qabstractaspect.h \
@@ -13,8 +12,7 @@ HEADERS += \
$$PWD/qabstractaspect_p.h \
$$PWD/qaspectengine_p.h \
$$PWD/qaspectfactory_p.h \
- $$PWD/qaspectmanager_p.h \
- $$PWD/qaspectthread_p.h
+ $$PWD/qaspectmanager_p.h
INCLUDEPATH += $$PWD
diff --git a/src/core/aspects/qaspectengine.cpp b/src/core/aspects/qaspectengine.cpp
index 222c4c2af..2e7e51247 100644
--- a/src/core/aspects/qaspectengine.cpp
+++ b/src/core/aspects/qaspectengine.cpp
@@ -47,7 +47,6 @@
#include <QtCore/QMetaObject>
#include <Qt3DCore/private/corelogging_p.h>
-#include <Qt3DCore/private/qaspectthread_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qchangearbiter_p.h>
#include <Qt3DCore/private/qeventfilterservice_p.h>
@@ -74,6 +73,7 @@ QAspectEnginePrivate *QAspectEnginePrivate::get(QAspectEngine *q)
QAspectEnginePrivate::QAspectEnginePrivate()
: QObjectPrivate()
+ , m_aspectManager(nullptr)
, m_postman(nullptr)
, m_scene(nullptr)
, m_initialized(false)
@@ -185,8 +185,7 @@ QAspectEngine::QAspectEngine(QObject *parent)
d->m_scene = new QScene(this);
d->m_postman = new QPostman(this);
d->m_postman->setScene(d->m_scene);
- d->m_aspectThread = new QAspectThread(this);
- d->m_aspectThread->waitForStart(QThread::HighestPriority);
+ d->m_aspectManager = new QAspectManager(this);
}
/*!
@@ -206,11 +205,6 @@ QAspectEngine::~QAspectEngine()
for (auto aspect : aspects)
unregisterAspect(aspect);
- // Wait for thread to have completed it's final loop of execution
- d->m_aspectThread->aspectManager()->quit();
- d->m_aspectThread->wait();
-
- delete d->m_aspectThread;
delete d->m_postman;
delete d->m_scene;
}
@@ -225,15 +219,12 @@ void QAspectEnginePrivate::initNodeTree(QNode *node)
void QAspectEnginePrivate::initialize()
{
- QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter();
+ m_aspectManager->initialize();
+ QChangeArbiter *arbiter = m_aspectManager->changeArbiter();
m_scene->setArbiter(arbiter);
QChangeArbiter::createUnmanagedThreadLocalChangeQueue(arbiter);
- QMetaObject::invokeMethod(arbiter,
- "setPostman",
- Q_ARG(Qt3DCore::QAbstractPostman*, m_postman));
- QMetaObject::invokeMethod(arbiter,
- "setScene",
- Q_ARG(Qt3DCore::QScene*, m_scene));
+ arbiter->setPostman(m_postman);
+ arbiter->setScene(m_scene);
m_initialized = true;
#if QT_CONFIG(qt3d_profile_jobs)
m_commandDebugger->setAspectEngine(q_func());
@@ -263,14 +254,14 @@ void QAspectEnginePrivate::shutdown()
// Cleanup the scene before quitting the backend
m_scene->setArbiter(nullptr);
- QChangeArbiter *arbiter = m_aspectThread->aspectManager()->changeArbiter();
+ QChangeArbiter *arbiter = m_aspectManager->changeArbiter();
QChangeArbiter::destroyUnmanagedThreadLocalChangeQueue(arbiter);
m_initialized = false;
}
void QAspectEnginePrivate::exitSimulationLoop()
{
- m_aspectThread->aspectManager()->exitSimulationLoop();
+ m_aspectManager->exitSimulationLoop();
}
/*!
@@ -285,12 +276,8 @@ void QAspectEngine::registerAspect(QAbstractAspect *aspect)
// AspectManager::registerAspect is called in the context
// of the AspectThread. This is turns call aspect->onInitialize
// still in the same AspectThread context
- aspect->moveToThread(d->m_aspectThread);
d->m_aspects << aspect;
- QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(),
- "registerAspect",
- Qt::BlockingQueuedConnection,
- Q_ARG(Qt3DCore::QAbstractAspect*, aspect));
+ d->m_aspectManager->registerAspect(aspect);
}
/*!
@@ -327,10 +314,7 @@ void QAspectEngine::unregisterAspect(QAbstractAspect *aspect)
// Tell the aspect manager to give the aspect a chance to do some cleanup
// in its QAbstractAspect::onUnregistered() virtual
- QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(),
- "unregisterAspect",
- Qt::BlockingQueuedConnection,
- Q_ARG(Qt3DCore::QAbstractAspect*, aspect));
+ d->m_aspectManager->unregisterAspect(aspect);
// Remove from our collection of named aspects (if present)
const auto it = std::find_if(d->m_namedAspects.begin(), d->m_namedAspects.end(),
@@ -455,14 +439,9 @@ void QAspectEngine::setRootEntity(QEntityPtr root)
// TODO: Pass the creation changes via the arbiter rather than relying upon
// an invokeMethod call.
qCDebug(Aspects) << "Begin setting scene root on aspect manager";
- QMetaObject::invokeMethod(d->m_aspectThread->aspectManager(),
- "setRootEntity",
- Qt::BlockingQueuedConnection,
- Q_ARG(Qt3DCore::QEntity*, root.data()),
- Q_ARG(QVector<Qt3DCore::QNodeCreatedChangeBasePtr>, d->m_creationChanges));
+ d->m_aspectManager->setRootEntity(root.data(), d->m_creationChanges);
qCDebug(Aspects) << "Done setting scene root on aspect manager";
-
- d->m_aspectThread->aspectManager()->enterSimulationLoop();
+ d->m_aspectManager->enterSimulationLoop();
}
/*!
diff --git a/src/core/aspects/qaspectengine_p.h b/src/core/aspects/qaspectengine_p.h
index 2d7d0fe93..9c042b5a5 100644
--- a/src/core/aspects/qaspectengine_p.h
+++ b/src/core/aspects/qaspectengine_p.h
@@ -65,7 +65,7 @@ namespace Qt3DCore {
class QEntity;
class QNode;
class QAspectEngine;
-class QAspectThread;
+class QAspectManager;
class QPostman;
class QScene;
@@ -84,7 +84,7 @@ public:
Q_DECLARE_PUBLIC(QAspectEngine)
QAspectFactory m_factory;
- QAspectThread *m_aspectThread;
+ QAspectManager *m_aspectManager;
QPostman *m_postman;
QScene *m_scene;
QSharedPointer<QEntity> m_root;
diff --git a/src/core/aspects/qaspectmanager.cpp b/src/core/aspects/qaspectmanager.cpp
index e9642116a..a028e38cb 100644
--- a/src/core/aspects/qaspectmanager.cpp
+++ b/src/core/aspects/qaspectmanager.cpp
@@ -61,6 +61,8 @@
#include <Qt3DCore/private/qtickclock_p.h>
#include <Qt3DCore/private/qtickclockservice_p.h>
+#include <QtCore/QCoreApplication>
+
#if defined(QT3D_CORE_JOB_TIMING)
#include <QElapsedTimer>
#endif
@@ -69,6 +71,26 @@ QT_BEGIN_NAMESPACE
namespace Qt3DCore {
+namespace {
+
+class RequestFrameEvent : public QEvent
+{
+public:
+ RequestFrameEvent()
+ : QEvent(static_cast<QEvent::Type>(RequestFrameEvent::requestEventType))
+ {}
+
+ static int eventType() { return RequestFrameEvent::requestEventType; }
+
+private:
+ static int requestEventType;
+};
+
+int RequestFrameEvent::requestEventType = QEvent::registerEventType();
+
+} // anonymous
+
+
/*!
\class Qt3DCore::QAspectManager
\internal
@@ -80,14 +102,9 @@ QAspectManager::QAspectManager(QObject *parent)
, m_jobManager(new QAspectJobManager(this))
, m_changeArbiter(new QChangeArbiter(this))
, m_serviceLocator(new QServiceLocator())
- , m_waitForEndOfSimulationLoop(0)
- , m_waitForStartOfSimulationLoop(0)
- , m_waitForEndOfExecLoop(0)
- , m_waitForQuit(0)
+ , m_simulationLoopRunning(false)
{
qRegisterMetaType<QSurface *>("QSurface*");
- m_runSimulationLoop.fetchAndStoreOrdered(0);
- m_runMainLoop.fetchAndStoreOrdered(1);
qCDebug(Aspects) << Q_FUNC_INFO;
}
@@ -102,15 +119,26 @@ QAspectManager::~QAspectManager()
void QAspectManager::enterSimulationLoop()
{
qCDebug(Aspects) << Q_FUNC_INFO;
- m_runSimulationLoop.fetchAndStoreOrdered(1);
+ m_simulationLoopRunning = true;
- // Wake up QAspectThread's event loop
- thread()->eventDispatcher()->wakeUp();
+ // Retrieve the frame advance service. Defaults to timer based if there is no renderer.
+ QAbstractFrameAdvanceService *frameAdvanceService =
+ m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
+
+ // Start the frameAdvanceService
+ frameAdvanceService->start();
+
+ // We are about to enter the simulation loop. Give aspects a chance to do any last
+ // pieces of initialization
+ qCDebug(Aspects) << "Calling onEngineStartup() for each aspect";
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ qCDebug(Aspects) << "\t" << aspect->objectName();
+ aspect->onEngineStartup();
+ }
+ qCDebug(Aspects) << "Done calling onEngineStartup() for each aspect";
- // We wait for the setRootEntity on the aspectManager to have completed
- // This ensures we cannot shutdown before the aspects have had a chance
- // to be initialized
- m_waitForStartOfSimulationLoop.acquire(1);
+ // Trigger event loop
+ requestNextFrame();
}
// Main thread (called by QAspectEngine)
@@ -119,7 +147,7 @@ void QAspectManager::exitSimulationLoop()
qCDebug(Aspects) << Q_FUNC_INFO;
// If this fails, simulation loop is already exited so nothing to do
- if (!m_runSimulationLoop.testAndSetOrdered(1, 0)) {
+ if (!m_simulationLoopRunning) {
qCDebug(Aspects) << "Simulation loop was not running. Nothing to do";
return;
}
@@ -141,17 +169,26 @@ void QAspectManager::exitSimulationLoop()
for (QAbstractAspect *aspect : qAsConst(m_aspects))
aspect->d_func()->onEngineAboutToShutdown();
+ // Process any pending changes from the frontend before we shut the aspects down
+ m_changeArbiter->syncChanges();
- qCDebug(Aspects) << "exitSimulationLoop waiting for exec loop to terminate";
- // Wait until the simulation loop is fully exited and the aspects are done
- // processing any final changes and have had onEngineShutdown() called on them
- m_waitForEndOfSimulationLoop.acquire(1);
+ // Give aspects a chance to perform any shutdown actions. This may include unqueuing
+ // any blocking work on the main thread that could potentially deadlock during shutdown.
+ qCDebug(Aspects) << "Calling onEngineShutdown() for each aspect";
+ for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
+ qCDebug(Aspects) << "\t" << aspect->objectName();
+ aspect->onEngineShutdown();
+ }
+ qCDebug(Aspects) << "Done calling onEngineShutdown() for each aspect";
+
+
+ m_simulationLoopRunning = false;
qCDebug(Aspects) << "exitSimulationLoop completed";
}
bool QAspectManager::isShuttingDown() const
{
- return !m_runSimulationLoop.load();
+ return !m_simulationLoopRunning;
}
/*!
@@ -184,7 +221,7 @@ void QAspectManager::shutdown()
// Aspects must be deleted in the Thread they were created in
}
-// QAspectThread:: queued invoked by QAspectEngine::setRootEntity
+// MainThread called by QAspectEngine::setRootEntity
void QAspectManager::setRootEntity(Qt3DCore::QEntity *root, const QVector<Qt3DCore::QNodeCreatedChangeBasePtr> &changes)
{
qCDebug(Aspects) << Q_FUNC_INFO;
@@ -251,118 +288,6 @@ void QAspectManager::unregisterAspect(Qt3DCore::QAbstractAspect *aspect)
qCDebug(Aspects) << "Completed unregistering aspect";
}
-void QAspectManager::exec()
-{
- // Gentlemen, start your engines
- QEventLoop eventLoop;
-
- // Enter the engine loop
- qCDebug(Aspects) << Q_FUNC_INFO << "***** Entering main loop *****";
- while (m_runMainLoop.load()) {
- // Process events until we're told to start the simulation loop
- while (m_runMainLoop.load() && !m_runSimulationLoop.load())
- eventLoop.processEvents(QEventLoop::AllEvents | QEventLoop::WaitForMoreEvents);
-
- if (!m_runSimulationLoop.load())
- break;
-
- // Retrieve the frame advance service. Defaults to timer based if there is no renderer.
- QAbstractFrameAdvanceService *frameAdvanceService =
- m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
-
- // Start the frameAdvanceService
- frameAdvanceService->start();
-
- // We are about to enter the simulation loop. Give aspects a chance to do any last
- // pieces of initialization
- qCDebug(Aspects) << "Calling onEngineStartup() for each aspect";
- for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
- qCDebug(Aspects) << "\t" << aspect->objectName();
- aspect->onEngineStartup();
- }
- qCDebug(Aspects) << "Done calling onEngineStartup() for each aspect";
- m_waitForStartOfSimulationLoop.release(1);
-
- // Only enter main simulation loop once the renderer and other aspects are initialized
- while (m_runSimulationLoop.load()) {
- qint64 t = frameAdvanceService->waitForNextFrame();
-
- // Distribute accumulated changes. This includes changes sent from the frontend
- // to the backend nodes. We call this before the call to m_scheduler->update() to ensure
- // that any property changes do not set dirty flags in a data race with the renderer's
- // submission thread which may be looking for dirty flags, acting upon them and then
- // clearing the dirty flags.
- //
- // Doing this as the first call in the new frame ensures the lock free approach works
- // without any such data race.
-#if QT_CONFIG(qt3d_profile_jobs)
- const quint32 arbiterId = 4096;
- JobRunStats changeArbiterStats;
- changeArbiterStats.jobId.typeAndInstance[0] = arbiterId;
- changeArbiterStats.jobId.typeAndInstance[1] = 0;
- changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
- changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
-#endif
- m_changeArbiter->syncChanges();
-#if QT_CONFIG(qt3d_profile_jobs)
- changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
- QThreadPooler::addJobLogStatsEntry(changeArbiterStats);
-#endif
-
- // For each Aspect
- // Ask them to launch set of jobs for the current frame
- // Updates matrices, bounding volumes, render bins ...
-#if defined(QT3D_CORE_JOB_TIMING)
- QElapsedTimer timer;
- timer.start();
-#endif
- m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
-#if defined(QT3D_CORE_JOB_TIMING)
- qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6;
-#endif
-
- // Process any pending events
- eventLoop.processEvents();
- } // End of simulation loop
-
- // Process any pending changes from the frontend before we shut the aspects down
- m_changeArbiter->syncChanges();
-
- // Give aspects a chance to perform any shutdown actions. This may include unqueuing
- // any blocking work on the main thread that could potentially deadlock during shutdown.
- qCDebug(Aspects) << "Calling onEngineShutdown() for each aspect";
- for (QAbstractAspect *aspect : qAsConst(m_aspects)) {
- qCDebug(Aspects) << "\t" << aspect->objectName();
- aspect->onEngineShutdown();
- }
- qCDebug(Aspects) << "Done calling onEngineShutdown() for each aspect";
-
- // Wake up the main thread which is waiting for us inside of exitSimulationLoop()
- m_waitForEndOfSimulationLoop.release(1);
- } // End of main loop
- qCDebug(Aspects) << Q_FUNC_INFO << "***** Exited main loop *****";
-
- m_waitForEndOfExecLoop.release(1);
- m_waitForQuit.acquire(1);
-}
-
-void QAspectManager::quit()
-{
- qCDebug(Aspects) << Q_FUNC_INFO;
-
- Q_ASSERT_X(m_runSimulationLoop.load() == 0, "QAspectManagr::quit()", "Inner loop is still running");
- m_runMainLoop.fetchAndStoreOrdered(0);
-
- // Wake up QAspectThread's event loop if needed
- thread()->eventDispatcher()->wakeUp();
-
- // We need to wait for the QAspectManager exec loop to terminate
- m_waitForEndOfExecLoop.acquire(1);
- m_waitForQuit.release(1);
-
- qCDebug(Aspects) << Q_FUNC_INFO << "Exiting";
-}
-
const QVector<QAbstractAspect *> &QAspectManager::aspects() const
{
return m_aspects;
@@ -383,7 +308,81 @@ QServiceLocator *QAspectManager::serviceLocator() const
return m_serviceLocator.data();
}
+/*!
+ \internal
+ \brief Drives the Qt3D simulation loop in the main thread
+ */
+bool QAspectManager::event(QEvent *e)
+{
+ if (e->type() == RequestFrameEvent::eventType()) {
+
+ // Process current frame
+ processFrame();
+
+ // Request next frame if we are still running
+ if (m_simulationLoopRunning)
+ requestNextFrame();
+ }
+
+ return QObject::event(e);
+}
+
+void QAspectManager::requestNextFrame()
+{
+ qCDebug(Aspects) << "Requesting new Frame";
+ // Post event in the event loop to force
+ // next frame to be processed
+ qApp->postEvent(this, new RequestFrameEvent());
+}
+
+void QAspectManager::processFrame()
+{
+ qCDebug(Aspects) << "Processing Frame";
+
+ // Retrieve the frame advance service. Defaults to timer based if there is no renderer.
+ QAbstractFrameAdvanceService *frameAdvanceService =
+ m_serviceLocator->service<QAbstractFrameAdvanceService>(QServiceLocator::FrameAdvanceService);
+
+ const qint64 t = frameAdvanceService->waitForNextFrame();
+
+ // Distribute accumulated changes. This includes changes sent from the frontend
+ // to the backend nodes. We call this before the call to m_scheduler->update() to ensure
+ // that any property changes do not set dirty flags in a data race with the renderer's
+ // submission thread which may be looking for dirty flags, acting upon them and then
+ // clearing the dirty flags.
+ //
+ // Doing this as the first call in the new frame ensures the lock free approach works
+ // without any such data race.
+#if QT_CONFIG(qt3d_profile_jobs)
+ const quint32 arbiterId = 4096;
+ JobRunStats changeArbiterStats;
+ changeArbiterStats.jobId.typeAndInstance[0] = arbiterId;
+ changeArbiterStats.jobId.typeAndInstance[1] = 0;
+ changeArbiterStats.threadId = reinterpret_cast<quint64>(QThread::currentThreadId());
+ changeArbiterStats.startTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
+#endif
+ // TO DO: Having this done in the main thread actually means aspects could just
+ // as simply read info out of the Frontend classes without risk of introducing
+ // races. This could therefore be removed for Qt 6.
+ m_changeArbiter->syncChanges();
+#if QT_CONFIG(qt3d_profile_jobs)
+ changeArbiterStats.endTime = QThreadPooler::m_jobsStatTimer.nsecsElapsed();
+ QThreadPooler::addJobLogStatsEntry(changeArbiterStats);
+#endif
+
+ // For each Aspect
+ // Ask them to launch set of jobs for the current frame
+ // Updates matrices, bounding volumes, render bins ...
+#if defined(QT3D_CORE_JOB_TIMING)
+ QElapsedTimer timer;
+ timer.start();
+#endif
+ m_scheduler->scheduleAndWaitForFrameAspectJobs(t);
+#if defined(QT3D_CORE_JOB_TIMING)
+ qDebug() << "Jobs took" << timer.nsecsElapsed() / 1.0e6;
+#endif
+}
+
} // namespace Qt3DCore
QT_END_NAMESPACE
-
diff --git a/src/core/aspects/qaspectmanager_p.h b/src/core/aspects/qaspectmanager_p.h
index de978b8e9..1c07ab797 100644
--- a/src/core/aspects/qaspectmanager_p.h
+++ b/src/core/aspects/qaspectmanager_p.h
@@ -95,9 +95,6 @@ public Q_SLOTS:
void registerAspect(Qt3DCore::QAbstractAspect *aspect);
void unregisterAspect(Qt3DCore::QAbstractAspect *aspect);
- void exec();
- void quit();
-
public:
const QVector<QAbstractAspect *> &aspects() const;
QAbstractAspectJobManager *jobManager() const;
@@ -105,19 +102,20 @@ public:
QServiceLocator *serviceLocator() const;
private:
+ bool event(QEvent *event) override;
+ void requestNextFrame();
+ void processFrame();
+
QVector<QAbstractAspect *> m_aspects;
QEntity *m_root;
QVariantMap m_data;
QScheduler *m_scheduler;
QAbstractAspectJobManager *m_jobManager;
QChangeArbiter *m_changeArbiter;
- QAtomicInt m_runSimulationLoop;
- QAtomicInt m_runMainLoop;
QScopedPointer<QServiceLocator> m_serviceLocator;
- QSemaphore m_waitForEndOfSimulationLoop;
- QSemaphore m_waitForStartOfSimulationLoop;
- QSemaphore m_waitForEndOfExecLoop;
- QSemaphore m_waitForQuit;
+ bool m_mainLoopRunning;
+ bool m_simulationLoopRunning;
+
};
} // namespace Qt3DCore
diff --git a/src/core/aspects/qaspectthread.cpp b/src/core/aspects/qaspectthread.cpp
deleted file mode 100644
index 31715b04e..000000000
--- a/src/core/aspects/qaspectthread.cpp
+++ /dev/null
@@ -1,99 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#include "qaspectthread_p.h"
-
-#include <QtCore/QMutexLocker>
-
-#include <Qt3DCore/private/qaspectmanager_p.h>
-#include <Qt3DCore/private/corelogging_p.h>
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DCore {
-
-QAspectThread::QAspectThread(QObject *parent)
- : QThread(parent),
- m_aspectManager(nullptr),
- m_semaphore(0)
-{
- qCDebug(Aspects) << Q_FUNC_INFO;
-}
-
-QAspectThread::~QAspectThread()
-{
-}
-
-void QAspectThread::waitForStart(Priority priority)
-{
- qCDebug(Aspects) << "Starting QAspectThread and going to sleep until it is ready for us...";
- start(priority);
- m_semaphore.acquire();
- qCDebug(Aspects) << "QAspectThead is now ready & calling thread is now awake again";
-}
-
-void QAspectThread::run()
-{
- qCDebug(Aspects) << "Entering void QAspectThread::run()";
-
- m_aspectManager = new QAspectManager;
-
- // Load and initialize the aspects and any other core services
- // Done before releasing condition to make sure that Qml Components
- // Are exposed prior to Qml Engine source being set
- m_aspectManager->initialize();
-
- // Wake up the calling thread now that our worker objects are ready for action
- m_semaphore.release();
-
- // Enter the main loop
- m_aspectManager->exec();
-
- // Clean up
- m_aspectManager->shutdown();
-
- // Delete the aspect manager while we're still in the thread
- delete m_aspectManager;
-
- qCDebug(Aspects) << "Exiting void QAspectThread::run()";
-}
-
-} // namespace Qt3DCore
-
-QT_END_NAMESPACE
diff --git a/src/core/aspects/qaspectthread_p.h b/src/core/aspects/qaspectthread_p.h
deleted file mode 100644
index 8ae9ff86d..000000000
--- a/src/core/aspects/qaspectthread_p.h
+++ /dev/null
@@ -1,88 +0,0 @@
-/****************************************************************************
-**
-** Copyright (C) 2014 Klaralvdalens Datakonsult AB (KDAB).
-** Contact: https://www.qt.io/licensing/
-**
-** This file is part of the Qt3D module of the Qt Toolkit.
-**
-** $QT_BEGIN_LICENSE:LGPL$
-** Commercial License Usage
-** Licensees holding valid commercial Qt licenses may use this file in
-** accordance with the commercial license agreement provided with the
-** Software or, alternatively, in accordance with the terms contained in
-** a written agreement between you and The Qt Company. For licensing terms
-** and conditions see https://www.qt.io/terms-conditions. For further
-** information use the contact form at https://www.qt.io/contact-us.
-**
-** GNU Lesser General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU Lesser
-** General Public License version 3 as published by the Free Software
-** Foundation and appearing in the file LICENSE.LGPL3 included in the
-** packaging of this file. Please review the following information to
-** ensure the GNU Lesser General Public License version 3 requirements
-** will be met: https://www.gnu.org/licenses/lgpl-3.0.html.
-**
-** GNU General Public License Usage
-** Alternatively, this file may be used under the terms of the GNU
-** General Public License version 2.0 or (at your option) the GNU General
-** Public license version 3 or any later version approved by the KDE Free
-** Qt Foundation. The licenses are as published by the Free Software
-** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
-** included in the packaging of this file. Please review the following
-** information to ensure the GNU General Public License requirements will
-** be met: https://www.gnu.org/licenses/gpl-2.0.html and
-** https://www.gnu.org/licenses/gpl-3.0.html.
-**
-** $QT_END_LICENSE$
-**
-****************************************************************************/
-
-#ifndef QT3DCORE_QASPECTTHREAD_P_H
-#define QT3DCORE_QASPECTTHREAD_P_H
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <Qt3DCore/qt3dcore_global.h>
-#include <QtCore/QSemaphore>
-#include <QtCore/QThread>
-
-
-QT_BEGIN_NAMESPACE
-
-namespace Qt3DCore {
-
-class QAspectManager;
-
-class QAspectThread : public QThread
-{
- Q_OBJECT
-public:
- explicit QAspectThread(QObject *parent = 0);
- ~QAspectThread();
-
- void waitForStart(Priority priority);
-
- QAspectManager *aspectManager() const { return m_aspectManager; }
-
-protected:
- void run() override;
-
-private:
- QAspectManager *m_aspectManager;
- QSemaphore m_semaphore;
-};
-
-} // namespace Qt3DCore
-
-QT_END_NAMESPACE
-
-#endif // QT3DCORE_QASPECTTHREAD_P_H
diff --git a/src/core/qchangearbiter_p.h b/src/core/qchangearbiter_p.h
index 1f453ff56..c7d96b593 100644
--- a/src/core/qchangearbiter_p.h
+++ b/src/core/qchangearbiter_p.h
@@ -109,8 +109,8 @@ public:
void sceneChangeEventWithLock(const QSceneChangePtr &e) override; // QLockableObserverInterface impl
void sceneChangeEventWithLock(const QSceneChangeList &e) override; // QLockableObserverInterface impl
- Q_INVOKABLE void setPostman(Qt3DCore::QAbstractPostman *postman);
- Q_INVOKABLE void setScene(Qt3DCore::QScene *scene);
+ void setPostman(Qt3DCore::QAbstractPostman *postman);
+ void setScene(Qt3DCore::QScene *scene);
QAbstractPostman *postman() const final;
QScene *scene() const;
diff --git a/src/core/services/qdownloadhelperservice.cpp b/src/core/services/qdownloadhelperservice.cpp
index 4cd89c5d0..deddf3ae0 100644
--- a/src/core/services/qdownloadhelperservice.cpp
+++ b/src/core/services/qdownloadhelperservice.cpp
@@ -39,10 +39,10 @@
#include "qdownloadhelperservice_p.h"
#include "qdownloadnetworkworker_p.h"
+#include <QtCore/QThread>
#include <Qt3DCore/QAspectEngine>
#include <Qt3DCore/private/qabstractserviceprovider_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
-#include <Qt3DCore/private/qaspectthread_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
#include <Qt3DCore/private/qservicelocator_p.h>
@@ -196,7 +196,7 @@ QString QDownloadHelperService::urlToLocalFileOrQrc(const QUrl &url)
QDownloadHelperService *QDownloadHelperService::getService(QAspectEngine *engine)
{
auto enginePrivate = Qt3DCore::QAspectEnginePrivate::get(engine);
- return enginePrivate->m_aspectThread->aspectManager()->serviceLocator()->downloadHelperService();
+ return enginePrivate->m_aspectManager->serviceLocator()->downloadHelperService();
}
bool QDownloadHelperService::isLocal(const QUrl &url)
diff --git a/src/input/backend/eventsourcesetterhelper.cpp b/src/input/backend/eventsourcesetterhelper.cpp
index bbc7ea54c..fe800a1a4 100644
--- a/src/input/backend/eventsourcesetterhelper.cpp
+++ b/src/input/backend/eventsourcesetterhelper.cpp
@@ -56,21 +56,21 @@ EventSourceSetterHelper::EventSourceSetterHelper(InputHandler *inputHandler)
{
}
-// Aspect thread
+// Main thread
void EventSourceSetterHelper::setEventFilterService(Qt3DCore::QEventFilterService *service)
{
- QMutexLocker lock(&m_mutex);
m_service = service;
}
-// Any thread
+// Main thread
void EventSourceSetterHelper::setEventSource(QObject *eventSource)
{
if (eventSource && m_lastEventSource != eventSource) {
- QMetaObject::invokeMethod(this,
- "setEventSourceHelper",
- Qt::BlockingQueuedConnection,
- Q_ARG(QObject*, eventSource));
+ if (m_service) {
+ m_service->initialize(eventSource);
+ m_inputHandler->registerEventFilters(m_service);
+ m_lastEventSource = eventSource;
+ }
}
}
@@ -83,17 +83,6 @@ void EventSourceSetterHelper::unsetEventSource(QObject *eventSource)
}
}
-// Main Thread
-void EventSourceSetterHelper::setEventSourceHelper(QObject *eventSource)
-{
- QMutexLocker lock(&m_mutex);
- if (m_service) {
- m_service->initialize(eventSource);
- m_inputHandler->registerEventFilters(m_service);
- m_lastEventSource = eventSource;
- }
-}
-
} // Input
} // Qt3DInput
diff --git a/src/input/backend/eventsourcesetterhelper_p.h b/src/input/backend/eventsourcesetterhelper_p.h
index 48418f1b9..b8800d8a6 100644
--- a/src/input/backend/eventsourcesetterhelper_p.h
+++ b/src/input/backend/eventsourcesetterhelper_p.h
@@ -75,14 +75,10 @@ public:
// Called from aspect thread
void setEventFilterService(Qt3DCore::QEventFilterService *service);
- // Called from any thread
+ // Called from main thread
void setEventSource(QObject *eventSource);
void unsetEventSource(QObject *eventSource);
-private Q_SLOTS:
- // Called in main thread
- void setEventSourceHelper(QObject *);
-
private:
Qt3DCore::QEventFilterService *m_service;
InputHandler *m_inputHandler;
diff --git a/src/input/backend/inputhandler.cpp b/src/input/backend/inputhandler.cpp
index 18559e9d4..9484909ab 100644
--- a/src/input/backend/inputhandler.cpp
+++ b/src/input/backend/inputhandler.cpp
@@ -127,58 +127,55 @@ void InputHandler::unregisterEventFilters(Qt3DCore::QEventFilterService *service
// Called by the keyboardEventFilter in the main thread
void InputHandler::appendKeyEvent(const QT_PREPEND_NAMESPACE(QKeyEvent) &event)
{
- QMutexLocker lock(&m_mutex);
m_pendingKeyEvents.append(event);
}
-// Called by QInputASpect::jobsToExecute (aspectThread)
+// Called by QInputASpect::jobsToExecute (Main Thread)
QList<QT_PREPEND_NAMESPACE(QKeyEvent)> InputHandler::pendingKeyEvents()
{
- QMutexLocker lock(&m_mutex);
return std::move(m_pendingKeyEvents);
}
-// Called by QInputASpect::jobsToExecute (aspectThread)
+// Called by QInputASpect::jobsToExecute (Main Thread)
void InputHandler::clearPendingKeyEvents()
{
- QMutexLocker lock(&m_mutex);
m_pendingKeyEvents.clear();
}
+// Main Thread
void InputHandler::appendMouseEvent(const QT_PREPEND_NAMESPACE(QMouseEvent) &event)
{
- QMutexLocker lock(&m_mutex);
m_pendingMouseEvents.append(event);
}
+// Main Thread
QList<QT_PREPEND_NAMESPACE(QMouseEvent)> InputHandler::pendingMouseEvents()
{
- QMutexLocker lock(&m_mutex);
return std::move(m_pendingMouseEvents);
}
+// Main Thread
void InputHandler::clearPendingMouseEvents()
{
- QMutexLocker lock(&m_mutex);
m_pendingMouseEvents.clear();
}
#if QT_CONFIG(wheelevent)
+// Main Thread
void InputHandler::appendWheelEvent(const QT_PREPEND_NAMESPACE(QWheelEvent) &event)
{
- QMutexLocker lock(&m_mutex);
m_pendingWheelEvents.append(event);
}
+// Main Thread
QList<QT_PREPEND_NAMESPACE (QWheelEvent)> Qt3DInput::Input::InputHandler::pendingWheelEvents()
{
- QMutexLocker lock(&m_mutex);
return std::move(m_pendingWheelEvents);
}
+// Main Thread
void InputHandler::clearPendingWheelEvents()
{
- QMutexLocker lock(&m_mutex);
m_pendingWheelEvents.clear();
}
#endif
@@ -253,7 +250,6 @@ QVector<Qt3DCore::QAspectJobPtr> InputHandler::mouseJobs()
#if QT_CONFIG(wheelevent)
const QList<QT_PREPEND_NAMESPACE(QWheelEvent)> wheelEvents = pendingWheelEvents();
#endif
-
for (const HMouseDevice &cHandle : qAsConst(m_activeMouseDevices)) {
MouseDevice *controller = m_mouseDeviceManager->data(cHandle);
diff --git a/src/input/backend/mousedevice.cpp b/src/input/backend/mousedevice.cpp
index 128988637..e285783b7 100644
--- a/src/input/backend/mousedevice.cpp
+++ b/src/input/backend/mousedevice.cpp
@@ -150,6 +150,7 @@ void MouseDevice::updateWheelEvents(const QList<QT_PREPEND_NAMESPACE (QWheelEven
}
#endif
+// Main Thread
void MouseDevice::updateMouseEvents(const QList<QT_PREPEND_NAMESPACE(QMouseEvent)> &events)
{
// Reset axis values before we accumulate new values for this frame
diff --git a/src/logic/executor.cpp b/src/logic/executor.cpp
index 6134e801e..1c428db47 100644
--- a/src/logic/executor.cpp
+++ b/src/logic/executor.cpp
@@ -64,8 +64,6 @@ void Executor::clearQueueAndProceed()
// If the semaphore is acquired, release it to allow the logic job and hence the
// manager and frame to complete and shutdown to continue.
m_nodeIds.clear();
- if (m_semaphore->available() == 0)
- m_semaphore->release();
}
void Executor::enqueueLogicFrameUpdates(const QVector<Qt3DCore::QNodeId> &nodeIds)
@@ -92,16 +90,12 @@ bool Executor::event(QEvent *e)
void Executor::processLogicFrameUpdates(float dt)
{
Q_ASSERT(m_scene);
- Q_ASSERT(m_semaphore);
const QVector<QNode *> nodes = m_scene->lookupNodes(m_nodeIds);
for (QNode *node : nodes) {
QFrameAction *frameAction = qobject_cast<QFrameAction *>(node);
if (frameAction && frameAction->isEnabled())
frameAction->onTriggered(dt);
}
-
- // Release the semaphore so the calling Manager can continue
- m_semaphore->release();
}
} // namespace Logic
diff --git a/src/logic/executor_p.h b/src/logic/executor_p.h
index e33ff842e..27b9c60c8 100644
--- a/src/logic/executor_p.h
+++ b/src/logic/executor_p.h
@@ -87,7 +87,6 @@ public:
explicit Executor(QObject *parent = 0);
void setScene(Qt3DCore::QScene *scene) { m_scene = scene; }
- void setSemephore(QSemaphore *semaphore) { m_semaphore = semaphore; }
void clearQueueAndProceed();
public Q_SLOTS:
@@ -100,7 +99,6 @@ protected:
private:
QVector<Qt3DCore::QNodeId> m_nodeIds;
Qt3DCore::QScene *m_scene;
- QSemaphore *m_semaphore;
};
} // namespace Logic
diff --git a/src/logic/manager.cpp b/src/logic/manager.cpp
index e10ace592..3d096a342 100644
--- a/src/logic/manager.cpp
+++ b/src/logic/manager.cpp
@@ -56,10 +56,8 @@ namespace Logic {
Manager::Manager()
: m_logicHandlerManager(new HandlerManager)
- , m_semaphore(1)
, m_dt(0.0f)
{
- m_semaphore.acquire();
}
Manager::~Manager()
@@ -69,8 +67,6 @@ Manager::~Manager()
void Manager::setExecutor(Executor *executor)
{
m_executor = executor;
- if (m_executor)
- m_executor->setSemephore(&m_semaphore);
}
void Manager::appendHandler(Handler *handler)
@@ -93,6 +89,7 @@ bool Manager::hasFrameActions() const
return m_logicHandlers.count() > 0;
}
+// Called from Job Thread
void Manager::triggerLogicFrameUpdates()
{
Q_ASSERT(m_executor);
@@ -107,7 +104,6 @@ void Manager::triggerLogicFrameUpdates()
// release the semaphore when it has completed its work.
m_executor->enqueueLogicFrameUpdates(m_logicComponentIds);
qApp->postEvent(m_executor, new FrameUpdateEvent(m_dt));
- m_semaphore.acquire();
}
} // namespace Logic
diff --git a/src/logic/manager_p.h b/src/logic/manager_p.h
index 918bd57e0..e4fa08a47 100644
--- a/src/logic/manager_p.h
+++ b/src/logic/manager_p.h
@@ -95,7 +95,6 @@ private:
QVector<Qt3DCore::QNodeId> m_logicComponentIds;
QLogicAspect *m_logicAspect;
Executor *m_executor;
- QSemaphore m_semaphore;
float m_dt;
};
diff --git a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp
index 454cb9f6a..b1597b095 100644
--- a/tests/benchmarks/render/jobs/tst_bench_jobs.cpp
+++ b/tests/benchmarks/render/jobs/tst_bench_jobs.cpp
@@ -48,7 +48,6 @@
#include <Qt3DCore/private/qaspectjobmanager_p.h>
#include <Qt3DCore/private/qaspectengine_p.h>
#include <Qt3DCore/private/qaspectmanager_p.h>
-#include <Qt3DCore/private/qaspectthread_p.h>
#include <Qt3DCore/private/qnodevisitor_p.h>
#include <Qt3DCore/private/qnodecreatedchangegenerator_p.h>
#include <QQmlComponent>