From f69edff5c0d0b868d937bebfa4623a9786c8da98 Mon Sep 17 00:00:00 2001 From: Klaus Basan Date: Mon, 7 Oct 2019 17:46:55 +0200 Subject: [PATCH] Ref T730, context shutdown * virtual function for "about to shutdown" * graceful shutdown --- src/blackcore/context/context.cpp | 10 ++++++++++ src/blackcore/context/context.h | 7 ++++--- src/blackcore/context/contextaudio.cpp | 17 +++++++++++++++-- src/blackcore/context/contextaudio.h | 3 +++ src/blackcore/corefacade.cpp | 1 + src/blackmisc/threadutils.cpp | 14 +++++++++----- 6 files changed, 42 insertions(+), 10 deletions(-) diff --git a/src/blackcore/context/context.cpp b/src/blackcore/context/context.cpp index a5054851c..cfec593a0 100644 --- a/src/blackcore/context/context.cpp +++ b/src/blackcore/context/context.cpp @@ -7,6 +7,7 @@ */ #include "blackcore/context/context.h" +#include "blackcore/application.h" #include "blackmisc/logcategorylist.h" using namespace BlackMisc; @@ -21,6 +22,15 @@ namespace BlackCore return cats; } + IContext::IContext(CCoreFacadeConfig::ContextMode mode, QObject *parent) : + QObject(parent), m_mode(mode), m_contextId(QDateTime::currentMSecsSinceEpoch()) + { + if (sApp && !sApp->isShuttingDown()) + { + QObject::connect(sApp, &CApplication::aboutToShutdown, this, &IContext::onAboutToShutdown); + } + } + IContextNetwork *IContext::getIContextNetwork() { return this->getRuntime()->getIContextNetwork(); diff --git a/src/blackcore/context/context.h b/src/blackcore/context/context.h index fd0a30b91..ba0c60afb 100644 --- a/src/blackcore/context/context.h +++ b/src/blackcore/context/context.h @@ -145,9 +145,7 @@ namespace BlackCore bool m_debugEnabled = false; //!< debug messages enabled //! Constructor - IContext(CCoreFacadeConfig::ContextMode mode, QObject *parent) : - QObject(parent), m_mode(mode), m_contextId(QDateTime::currentMSecsSinceEpoch()) - {} + IContext(CCoreFacadeConfig::ContextMode mode, QObject *parent); //! Path and context id QString buildPathAndContextId(const QString &path) const @@ -164,6 +162,9 @@ namespace BlackCore BlackMisc::CLogMessage(this, BlackMisc::CLogCategory::contextSlot()).warning(u"Empty context called, details: %1") << functionName; } + //! Called when shutdown is about to be called + virtual void onAboutToShutdown() {} + //! Standard message when status message is returned in empty context static const BlackMisc::CStatusMessage &statusMessageEmptyContext(); }; diff --git a/src/blackcore/context/contextaudio.cpp b/src/blackcore/context/contextaudio.cpp index 3901ee743..b816e0fd5 100644 --- a/src/blackcore/context/contextaudio.cpp +++ b/src/blackcore/context/contextaudio.cpp @@ -33,13 +33,18 @@ namespace BlackCore namespace Context { IContextAudio::IContextAudio(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime) : - IContext(mode, runtime), m_voiceClient("https://voice1.vatsim.uk") + IContext(mode, runtime), m_voiceClient("https://voice1.vatsim.uk", this) { + Q_ASSERT_X(CThreadUtils::isApplicationThread(m_voiceClient.thread()), Q_FUNC_INFO, "Should be in main thread"); + m_voiceClient.start(); + Q_ASSERT_X(m_voiceClient.owner() == this, Q_FUNC_INFO, "Wrong owner"); + Q_ASSERT_X(!CThreadUtils::isApplicationThread(m_voiceClient.thread()), Q_FUNC_INFO, "Must NOT be in main thread"); + const CSettings as = m_audioSettings.getThreadLocal(); this->setVoiceOutputVolume(as.getOutVolume()); m_selcalPlayer = new CSelcalPlayer(CAudioDeviceInfo::getDefaultOutputDevice(), this); - connect(&m_voiceClient, &CAfvClient::ptt, this, &IContextAudio::ptt); + connect(&m_voiceClient, &CAfvClient::ptt, this, &IContextAudio::ptt, Qt::QueuedConnection); this->changeDeviceSettings(); QPointer myself(this); @@ -97,6 +102,14 @@ namespace BlackCore m_voiceClient.stopAudio(); } + void IContextAudio::gracefulShutdown() + { + m_voiceClient.stopAudio(); + m_voiceClient.quitAndWait(); + Q_ASSERT_X(CThreadUtils::isCurrentThreadObjectThread(&m_voiceClient), Q_FUNC_INFO, "Needs to be back in current thread"); + QObject::disconnect(this); + } + const CIdentifier &IContextAudio::audioRunsWhere() const { static const CIdentifier i("IContextAudio"); diff --git a/src/blackcore/context/contextaudio.h b/src/blackcore/context/contextaudio.h index 4eff18a70..418966199 100644 --- a/src/blackcore/context/contextaudio.h +++ b/src/blackcore/context/contextaudio.h @@ -86,6 +86,9 @@ namespace BlackCore //! Destructor virtual ~IContextAudio() override; + //! Graceful shutdown + void gracefulShutdown(); + // -------- parts which can run in core and GUI, referring to local voice client ------------ //! Reference to voice client diff --git a/src/blackcore/corefacade.cpp b/src/blackcore/corefacade.cpp index 2a9eb261a..aaf8c1c93 100644 --- a/src/blackcore/corefacade.cpp +++ b/src/blackcore/corefacade.cpp @@ -354,6 +354,7 @@ namespace BlackCore { // there is no empty audio context since AFV disconnect(this->getIContextAudio()); + this->getIContextAudio()->gracefulShutdown(); this->getIContextAudio()->deleteLater(); m_contextAudio = nullptr; } diff --git a/src/blackmisc/threadutils.cpp b/src/blackmisc/threadutils.cpp index 2a05bda42..0e0b4578a 100644 --- a/src/blackmisc/threadutils.cpp +++ b/src/blackmisc/threadutils.cpp @@ -51,15 +51,19 @@ namespace BlackMisc static const QString normal("normal"); static const QString high("high"); static const QString highest("highest"); + static const QString time("time critical"); + static const QString inherit("inherit"); switch (priority) { - case QThread::IdlePriority: return idle; - case QThread::LowestPriority: return lowest; - case QThread::LowPriority: return low; - case QThread::NormalPriority: return normal; - case QThread::HighPriority: return high; + case QThread::IdlePriority: return idle; + case QThread::LowestPriority: return lowest; + case QThread::LowPriority: return low; + case QThread::NormalPriority: return normal; + case QThread::HighPriority: return high; case QThread::HighestPriority: return highest; + case QThread::InheritPriority: return inherit; + case QThread::TimeCriticalPriority: return time; default: break; }