Ref T730, context shutdown

* virtual function for "about to shutdown"
* graceful shutdown
This commit is contained in:
Klaus Basan
2019-10-07 17:46:55 +02:00
committed by Mat Sutcliffe
parent 857e3581b0
commit f69edff5c0
6 changed files with 42 additions and 10 deletions

View File

@@ -7,6 +7,7 @@
*/ */
#include "blackcore/context/context.h" #include "blackcore/context/context.h"
#include "blackcore/application.h"
#include "blackmisc/logcategorylist.h" #include "blackmisc/logcategorylist.h"
using namespace BlackMisc; using namespace BlackMisc;
@@ -21,6 +22,15 @@ namespace BlackCore
return cats; 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() IContextNetwork *IContext::getIContextNetwork()
{ {
return this->getRuntime()->getIContextNetwork(); return this->getRuntime()->getIContextNetwork();

View File

@@ -145,9 +145,7 @@ namespace BlackCore
bool m_debugEnabled = false; //!< debug messages enabled bool m_debugEnabled = false; //!< debug messages enabled
//! Constructor //! Constructor
IContext(CCoreFacadeConfig::ContextMode mode, QObject *parent) : IContext(CCoreFacadeConfig::ContextMode mode, QObject *parent);
QObject(parent), m_mode(mode), m_contextId(QDateTime::currentMSecsSinceEpoch())
{}
//! Path and context id //! Path and context id
QString buildPathAndContextId(const QString &path) const 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; 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 //! Standard message when status message is returned in empty context
static const BlackMisc::CStatusMessage &statusMessageEmptyContext(); static const BlackMisc::CStatusMessage &statusMessageEmptyContext();
}; };

View File

@@ -33,13 +33,18 @@ namespace BlackCore
namespace Context namespace Context
{ {
IContextAudio::IContextAudio(CCoreFacadeConfig::ContextMode mode, CCoreFacade *runtime) : 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(); const CSettings as = m_audioSettings.getThreadLocal();
this->setVoiceOutputVolume(as.getOutVolume()); this->setVoiceOutputVolume(as.getOutVolume());
m_selcalPlayer = new CSelcalPlayer(CAudioDeviceInfo::getDefaultOutputDevice(), this); 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(); this->changeDeviceSettings();
QPointer<IContextAudio> myself(this); QPointer<IContextAudio> myself(this);
@@ -97,6 +102,14 @@ namespace BlackCore
m_voiceClient.stopAudio(); 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 const CIdentifier &IContextAudio::audioRunsWhere() const
{ {
static const CIdentifier i("IContextAudio"); static const CIdentifier i("IContextAudio");

View File

@@ -86,6 +86,9 @@ namespace BlackCore
//! Destructor //! Destructor
virtual ~IContextAudio() override; virtual ~IContextAudio() override;
//! Graceful shutdown
void gracefulShutdown();
// -------- parts which can run in core and GUI, referring to local voice client ------------ // -------- parts which can run in core and GUI, referring to local voice client ------------
//! Reference to voice client //! Reference to voice client

View File

@@ -354,6 +354,7 @@ namespace BlackCore
{ {
// there is no empty audio context since AFV // there is no empty audio context since AFV
disconnect(this->getIContextAudio()); disconnect(this->getIContextAudio());
this->getIContextAudio()->gracefulShutdown();
this->getIContextAudio()->deleteLater(); this->getIContextAudio()->deleteLater();
m_contextAudio = nullptr; m_contextAudio = nullptr;
} }

View File

@@ -51,15 +51,19 @@ namespace BlackMisc
static const QString normal("normal"); static const QString normal("normal");
static const QString high("high"); static const QString high("high");
static const QString highest("highest"); static const QString highest("highest");
static const QString time("time critical");
static const QString inherit("inherit");
switch (priority) switch (priority)
{ {
case QThread::IdlePriority: return idle; case QThread::IdlePriority: return idle;
case QThread::LowestPriority: return lowest; case QThread::LowestPriority: return lowest;
case QThread::LowPriority: return low; case QThread::LowPriority: return low;
case QThread::NormalPriority: return normal; case QThread::NormalPriority: return normal;
case QThread::HighPriority: return high; case QThread::HighPriority: return high;
case QThread::HighestPriority: return highest; case QThread::HighestPriority: return highest;
case QThread::InheritPriority: return inherit;
case QThread::TimeCriticalPriority: return time;
default: break; default: break;
} }