Connection guard (detected during #477)

Disconnects Qt signal/slot conenction when destroyed
This commit is contained in:
Klaus Basan
2015-10-31 01:17:37 +01:00
committed by Mathew Sutcliffe
parent 3acf085b92
commit 23856bbc57
11 changed files with 124 additions and 34 deletions

View File

@@ -0,0 +1,45 @@
/* Copyright (C) 2015
* swift Project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
#include "connectionguard.h"
namespace BlackMisc
{
CConnectionGuard::CConnectionGuard(const QMetaObject::Connection &connection)
{
this->m_connections.append(connection);
}
void CConnectionGuard::append(const QMetaObject::Connection &connection)
{
this->m_connections.append(connection);
}
void CConnectionGuard::append(const QList<QMetaObject::Connection> &connections)
{
this->m_connections.append(connections);
}
CConnectionGuard::~CConnectionGuard()
{
disconnectAll();
}
int CConnectionGuard::disconnectAll()
{
if (this->m_connections.isEmpty()) { return 0; }
int c = 0;
for (const QMetaObject::Connection &con : this->m_connections)
{
if (QObject::disconnect(con)) { c++; }
}
this->m_connections.clear();
return c;
}
} // ns

View File

@@ -0,0 +1,54 @@
/* Copyright (C) 2015
* swift project Community / Contributors
*
* This file is part of swift project. It is subject to the license terms in the LICENSE file found in the top-level
* directory of this distribution and at http://www.swift-project.org/license.html. No part of swift project,
* including this file, may be copied, modified, propagated, or distributed except according to the terms
* contained in the LICENSE file.
*/
//! \file
#ifndef BLACKMISC_CONNECTIONGUARD_H
#define BLACKMISC_CONNECTIONGUARD_H
#include "blackmisc/blackmiscexport.h"
#include <QList>
#include <QObject>
namespace BlackMisc
{
/*!
* List of QMetaObject::Connection. The trick here is that those connections will
* be disconnected when the object is destroyed. So it can be used with lambdas or bind which feature
* non QObjects, if those might be destroyed before the signaling QObject.
*/
class BLACKMISC_EXPORT CConnectionGuard : public QObject
{
Q_OBJECT
public:
//! Constructor
CConnectionGuard() = default;
//! Constructor
CConnectionGuard(const QMetaObject::Connection &connection);
//! Destructor
~CConnectionGuard();
//! Add connection
void append(const QMetaObject::Connection &connection);
//! Add connections
void append(const QList<QMetaObject::Connection> &connections);
//! Disconnect all
int disconnectAll();
private:
QList<QMetaObject::Connection> m_connections;
};
} // BlackMisc
#endif

View File

@@ -21,7 +21,7 @@ namespace BlackMisc
{
CWebDataServicesAware::~CWebDataServicesAware()
{
disconnectSignals();
this->m_swiftConnections.disconnectAll();
}
CServerList CWebDataServicesAware::getVatsimFsdServers() const
@@ -264,7 +264,7 @@ namespace BlackMisc
void CWebDataServicesAware::setProvider(IWebDataServicesProvider *webDataReaderProvider)
{
Q_ASSERT_X(webDataReaderProvider, Q_FUNC_INFO, "missing provider");
disconnectSignals();
this->m_swiftConnections.disconnectAll();
m_webDataReaderProvider = webDataReaderProvider;
}
@@ -275,7 +275,7 @@ namespace BlackMisc
void CWebDataServicesAware::gracefulShutdown()
{
disconnectSignals();
this->m_swiftConnections.disconnectAll();
this->m_webDataReaderProvider = nullptr;
}
@@ -317,13 +317,5 @@ namespace BlackMisc
return this->m_webDataReaderProvider->readDbDataFromDisk(dir, inBackround);
}
void CWebDataServicesAware::disconnectSignals()
{
for (QMetaObject::Connection &c : m_swiftConnections)
{
QObject::disconnect(c);
}
m_swiftConnections.clear();
}
} // namespace
} // namespace

View File

@@ -26,6 +26,7 @@
#include "blackmisc/simulation/simulatedaircraft.h"
#include "blackmisc/weather/metarset.h"
#include "blackmisc/countrylist.h"
#include "blackmisc/connectionguard.h"
#include <functional>
@@ -343,8 +344,8 @@ namespace BlackMisc
CWebDataServicesAware(IWebDataServicesProvider *webDataReaderProvider = nullptr) : m_webDataReaderProvider(webDataReaderProvider) { }
private:
IWebDataServicesProvider *m_webDataReaderProvider = nullptr; //!< access to object
QList<QMetaObject::Connection> m_swiftConnections; //!< signal connection with swift
IWebDataServicesProvider *m_webDataReaderProvider = nullptr; //!< access to object
BlackMisc::CConnectionGuard m_swiftConnections; //!< signal connection with swift
//! Disconnect all signals
void disconnectSignals();

View File

@@ -110,7 +110,7 @@ namespace BlackMisc
virtual QList<QMetaObject::Connection> connectRemoteAircraftProviderSignals(
QObject *receiver,
std::function<void(const BlackMisc::Aviation::CAircraftSituation &)> addedSituationSlot,
std::function<void(const BlackMisc::Aviation::CCallsign &, const BlackMisc::Aviation::CAircraftParts &)> addedPartsSlot,
std::function<void(const BlackMisc::Aviation::CCallsign &, const BlackMisc::Aviation::CAircraftParts &)> addedPartsSlot,
std::function<void(const BlackMisc::Aviation::CCallsign &)> removedAircraftSlot,
std::function<void(const BlackMisc::Simulation::CAirspaceAircraftSnapshot &)> aircraftSnapshot
) = 0;

View File

@@ -72,10 +72,10 @@ namespace BlackMisc
QList<QMetaObject::Connection> CRemoteAircraftProviderDummy::connectRemoteAircraftProviderSignals(
QObject *receiver,
std::function<void (const CAircraftSituation &)> situationSlot,
std::function<void (const BlackMisc::Aviation::CCallsign &, const CAircraftParts &)> partsSlot,
std::function<void (const CCallsign &)> removedAircraftSlot,
std::function<void (const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot
std::function<void (const CAircraftSituation &)> situationSlot,
std::function<void (const BlackMisc::Aviation::CCallsign &, const CAircraftParts &)> partsSlot,
std::function<void (const CCallsign &)> removedAircraftSlot,
std::function<void (const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot
)
{
Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");