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

@@ -149,10 +149,10 @@ namespace BlackCore
QList<QMetaObject::Connection> CAirspaceMonitor::connectRemoteAircraftProviderSignals(
QObject *receiver,
std::function<void(const CAircraftSituation &)> situationSlot,
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 CCallsign &)> removedAircraftSlot,
std::function<void(const CAirspaceAircraftSnapshot &)> aircraftSnapshotSlot
)
{
Q_ASSERT_X(receiver, Q_FUNC_INFO, "Missing receiver");

View File

@@ -35,12 +35,14 @@ namespace BlackCore
this->setObjectName("Simulator:" + info.getIdentifier());
// provider signals
m_remoteAircraftProviderConnections = this->m_remoteAircraftProvider->connectRemoteAircraftProviderSignals(
m_remoteAircraftProviderConnections.append(
this->m_remoteAircraftProvider->connectRemoteAircraftProviderSignals(
this, // receiver must match object in bind
std::bind(&CSimulatorCommon::ps_remoteProviderAddAircraftSituation, this, std::placeholders::_1),
std::bind(&CSimulatorCommon::ps_remoteProviderAddAircraftParts, this, std::placeholders::_1, std::placeholders::_2),
std::bind(&CSimulatorCommon::ps_remoteProviderRemovedAircraft, this, std::placeholders::_1),
std::bind(&CSimulatorCommon::ps_recalculateRenderedAircraft, this, std::placeholders::_1));
std::bind(&CSimulatorCommon::ps_recalculateRenderedAircraft, this, std::placeholders::_1))
);
// timer
this->m_oneSecondTimer.setObjectName(this->objectName().append(":m_oneSecondTimer"));
@@ -219,14 +221,7 @@ namespace BlackCore
void CSimulatorCommon::unload()
{
this->disconnectFrom(); // disconnect from simulator
// disconnect as many signals as possible
for (const QMetaObject::Connection &c : m_remoteAircraftProviderConnections)
{
QObject::disconnect(c);
}
m_remoteAircraftProviderConnections.clear();
this->disconnect();
this->m_remoteAircraftProviderConnections.disconnectAll();
CLogHandler::instance()->disconnect();
}

View File

@@ -27,6 +27,7 @@
#include "blackmisc/network/textmessage.h"
#include "blackmisc/network/client.h"
#include "blackmisc/pixmap.h"
#include "blackmisc/connectionguard.h"
#include <QObject>
namespace BlackCore
@@ -137,7 +138,7 @@ namespace BlackCore
bool setInitialAircraftSituation(BlackMisc::Simulation::CSimulatedAircraft &aircraft) const;
protected:
IInterpolator *m_interpolator = nullptr; //!< interpolator instance
IInterpolator *m_interpolator = nullptr; //!< interpolator instance
bool m_pausedSimFreezesInterpolation = false; //!< paused simulator will also pause interpolation (so AI aircraft will hold)
private:
@@ -152,7 +153,7 @@ namespace BlackCore
BlackMisc::Aviation::CCallsignSet m_callsignsToBeRendered; //!< callsigns which will be rendered
int m_maxRenderedAircraft = MaxAircraftInfinite; //!< max.rendered aircraft
BlackMisc::PhysicalQuantities::CLength m_maxRenderedDistance { 0.0, BlackMisc::PhysicalQuantities::CLengthUnit::nullUnit()}; //!< max.distance for rendering
QList<QMetaObject::Connection> m_remoteAircraftProviderConnections; //!< connected signal/slots
BlackMisc::CConnectionGuard m_remoteAircraftProviderConnections; //!< connected signal/slots
};
} // namespace

View File

@@ -42,6 +42,7 @@ namespace BlackGui
this->m_parentDockableInfoArea = nullptr;
});
Q_ASSERT_X(con, Q_FUNC_INFO, "Connection failed");
this->m_connections.append(con);
return true;
}

View File

@@ -16,7 +16,7 @@
#include "blackgui/dockwidgetinfoarea.h"
#include "blackgui/infoarea.h"
#include "blackgui/enableforframelesswindow.h"
#include "blackmisc/qtconnectionlist.h"
#include "blackmisc/connectionguard.h"
#include <QWidget>
namespace BlackGui
@@ -69,6 +69,7 @@ namespace BlackGui
private:
BlackGui::CDockWidgetInfoArea *m_parentDockableInfoArea = nullptr; //!< my parent dockable widget
BlackMisc::CConnectionGuard m_connections;
};
}
} // namespace

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");