From 7ffa27f86a09b1f1a53a8bf019edf0157d36567b Mon Sep 17 00:00:00 2001 From: Don Gagne Date: Wed, 10 Dec 2014 15:36:08 -0800 Subject: [PATCH] New Singleton Manager --- .../AutoPilotPluginManager.cc | 20 +-- src/AutoPilotPlugins/AutoPilotPluginManager.h | 9 +- .../PX4/Tests/FlightModeConfigTest.cc | 8 +- src/FactSystem/FactSystem.cc | 31 +---- src/FactSystem/FactSystem.h | 16 +-- src/QGCApplication.cc | 40 ++---- src/QGCApplication.h | 16 +-- src/QGCSingleton.cc | 6 +- src/QGCSingleton.h | 129 ++++++++++++++++-- src/comm/LinkManager.cc | 29 +--- src/comm/LinkManager.h | 23 ++-- src/qgcunittest/LinkManagerTest.cc | 15 +- src/qgcunittest/LinkManagerTest.h | 1 - src/qgcunittest/MavlinkLogTest.cc | 4 +- src/qgcunittest/MockUASManager.cc | 2 +- src/qgcunittest/PX4RCCalibrationTest.cc | 7 +- src/qgcunittest/QGCUASFileManagerTest.cc | 4 +- src/qgcunittest/TCPLinkTest.cc | 4 +- src/qgcunittest/UASUnitTest.cc | 4 +- src/qgcunittest/UnitTest.cc | 6 +- src/uas/UASManager.cc | 68 +++------ src/uas/UASManager.h | 20 +-- src/uas/UASManagerInterface.h | 10 +- 23 files changed, 210 insertions(+), 262 deletions(-) diff --git a/src/AutoPilotPlugins/AutoPilotPluginManager.cc b/src/AutoPilotPlugins/AutoPilotPluginManager.cc index de27c15ac..ac4de4f92 100644 --- a/src/AutoPilotPlugins/AutoPilotPluginManager.cc +++ b/src/AutoPilotPlugins/AutoPilotPluginManager.cc @@ -29,25 +29,7 @@ #include "Generic/GenericAutoPilotPlugin.h" #include "QGCApplication.h" -AutoPilotPluginManager* AutoPilotPluginManager::_instance = NULL; - -AutoPilotPluginManager* AutoPilotPluginManager::instance(void) -{ - if (_instance == NULL) { - _instance = new AutoPilotPluginManager(qgcApp()); - Q_CHECK_PTR(_instance); - } - - Q_ASSERT(_instance); - - return _instance; -} - -void AutoPilotPluginManager::deleteInstance(void) -{ - _instance = NULL; - delete this; -} +IMPLEMENT_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager) AutoPilotPluginManager::AutoPilotPluginManager(QObject* parent) : QGCSingleton(parent) diff --git a/src/AutoPilotPlugins/AutoPilotPluginManager.h b/src/AutoPilotPlugins/AutoPilotPluginManager.h index 073b166bc..b3b242e1f 100644 --- a/src/AutoPilotPlugins/AutoPilotPluginManager.h +++ b/src/AutoPilotPlugins/AutoPilotPluginManager.h @@ -41,13 +41,10 @@ class AutoPilotPluginManager : public QGCSingleton { Q_OBJECT + + DECLARE_QGC_SINGLETON(AutoPilotPluginManager, AutoPilotPluginManager) public: - /// @brief Returns the AutoPilotPluginManager singleton - static AutoPilotPluginManager* instance(void); - - virtual void deleteInstance(void); - /// @brief Returns the singleton AutoPilot instance for the specified auto pilot type. /// @param autopilotType Specified using the MAV_AUTOPILOT_* values. AutoPilotPlugin* getInstanceForAutoPilotPlugin(int autopilotType); @@ -56,8 +53,6 @@ private: /// All access to singleton is through AutoPilotPluginManager::instance AutoPilotPluginManager(QObject* parent = NULL); - static AutoPilotPluginManager* _instance; - QMap _pluginMap; }; diff --git a/src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.cc b/src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.cc index 0fc4b09dc..17e84034b 100644 --- a/src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.cc +++ b/src/AutoPilotPlugins/PX4/Tests/FlightModeConfigTest.cc @@ -54,7 +54,7 @@ void FlightModeConfigTest::init(void) _mockUASManager = new MockUASManager(); Q_ASSERT(_mockUASManager); - UASManager::setMockUASManager(_mockUASManager); + UASManager::setMockInstance(_mockUASManager); _mockUAS = new MockUAS(); Q_CHECK_PTR(_mockUAS); @@ -126,21 +126,21 @@ void FlightModeConfigTest::init(void) void FlightModeConfigTest::cleanup(void) { - UnitTest::cleanup(); - Q_ASSERT(_configWidget); delete _configWidget; Q_ASSERT(_mockUAS); delete _mockUAS; - UASManager::setMockUASManager(NULL); + UASManager::setMockInstance(NULL); Q_ASSERT(_mockUASManager); delete _mockUASManager; _mapChannelCombo2Param.clear(); _mapChannelCombo2ButtonGroup.clear(); + + UnitTest::cleanup(); } /// @brief Returns channel mapping for the specified parameters diff --git a/src/FactSystem/FactSystem.cc b/src/FactSystem/FactSystem.cc index 06a324fe7..401efd61d 100644 --- a/src/FactSystem/FactSystem.cc +++ b/src/FactSystem/FactSystem.cc @@ -26,37 +26,16 @@ #include "FactSystem.h" #include "UASManager.h" +#include "QGCApplication.h" #include -FactSystem* FactSystem::_instance = NULL; -QMutex FactSystem::_singletonLock; -const char* FactSystem::_factSystemQmlUri = "QGroundControl.FactSystem"; - -FactSystem* FactSystem::instance(void) -{ - if(_instance == 0) { - _singletonLock.lock(); - if (_instance == 0) { - _instance = new FactSystem(qgcApp()); - Q_CHECK_PTR(_instance); - } - _singletonLock.unlock(); - } - - Q_ASSERT(_instance); - - return _instance; -} +IMPLEMENT_QGC_SINGLETON(FactSystem, FactSystem) -void FactSystem::deleteInstance(void) -{ - _instance = NULL; - delete this; -} +const char* FactSystem::_factSystemQmlUri = "QGroundControl.FactSystem"; -FactSystem::FactSystem(QObject* parent, bool registerSingleton) : - QGCSingleton(parent, registerSingleton) +FactSystem::FactSystem(QObject* parent) : + QGCSingleton(parent) { qmlRegisterType(_factSystemQmlUri, 1, 0, "Fact"); qmlRegisterType(_factSystemQmlUri, 1, 0, "FactValidator"); diff --git a/src/FactSystem/FactSystem.h b/src/FactSystem/FactSystem.h index 910018817..93716c893 100644 --- a/src/FactSystem/FactSystem.h +++ b/src/FactSystem/FactSystem.h @@ -33,8 +33,6 @@ #include "QGCSingleton.h" #include "FactValidator.h" -#include - /// FactSystem is a singleton which provides access to the Facts in the system /// /// The components of the FactSystem are a Fact which holds an individual value. FactMetaData holds @@ -47,22 +45,14 @@ class FactSystem : public QGCSingleton { Q_OBJECT -public: - /// Returns the FactSystem singleton - static FactSystem* instance(void); - - /// Override from QGCSingleton - virtual void deleteInstance(void); - - ~FactSystem(); + DECLARE_QGC_SINGLETON(FactSystem, FactSystem) private: /// All access to FactSystem is through FactSystem::instance, so constructor is private - FactSystem(QObject* parent = NULL, bool registerSingleton = true); + FactSystem(QObject* parent = NULL); - static QMutex _singletonLock; ///< Mutex to make calls to instance thread-safe + ~FactSystem(); - static FactSystem* _instance; ///< FactSystem singleton static const char* _factSystemQmlUri; ///< URI for FactSystem QML imports }; diff --git a/src/QGCApplication.cc b/src/QGCApplication.cc index 62482c249..d7f1cda30 100644 --- a/src/QGCApplication.cc +++ b/src/QGCApplication.cc @@ -175,7 +175,7 @@ QGCApplication::QGCApplication(int &argc, char* argv[], bool unitTesting) : QGCApplication::~QGCApplication() { - destroySingletonsForUnitTest(); + _destroySingletons(); } void QGCApplication::_initCommon(void) @@ -424,43 +424,33 @@ QGCApplication* qgcApp(void) /// up being creating on something other than the main thread. void QGCApplication::_createSingletons(void) { - - LinkManager* linkManager = LinkManager::instance(); + // The order here is important since the singletons reference each other + LinkManager* linkManager = LinkManager::_createSingleton(); Q_UNUSED(linkManager); Q_ASSERT(linkManager); - UASManagerInterface* uasManager = UASManager::instance(); + // Needs LinkManager + UASManagerInterface* uasManager = UASManager::_createSingleton(); Q_UNUSED(uasManager); Q_ASSERT(uasManager); - AutoPilotPluginManager* pluginManager = AutoPilotPluginManager::instance(); + // Need UASManager + AutoPilotPluginManager* pluginManager = AutoPilotPluginManager::_createSingleton(); Q_UNUSED(pluginManager); Q_ASSERT(pluginManager); - // Must be after UASManager since FactSystem connects to UASManager - FactSystem* factSystem = FactSystem::instance(); + // Needs UASManager + FactSystem* factSystem = FactSystem::_createSingleton(); Q_UNUSED(factSystem); Q_ASSERT(factSystem); } -void QGCApplication::destroySingletonsForUnitTest(void) +void QGCApplication::_destroySingletons(void) { - foreach(QGCSingleton* singleton, _singletons) { - Q_ASSERT(singleton); - singleton->deleteInstance(); - } - - if (MainWindow::instance()) { - delete MainWindow::instance(); - } - - _singletons.clear(); -} + // Take down singletons in reverse order of creation -void QGCApplication::registerSingleton(QGCSingleton* singleton) -{ - Q_ASSERT(singleton); - Q_ASSERT(!_singletons.contains(singleton)); - - _singletons.append(singleton); + FactSystem::_deleteSingleton(); + AutoPilotPluginManager::_deleteSingleton(); + UASManager::_deleteSingleton(); + LinkManager::_deleteSingleton(); } diff --git a/src/QGCApplication.h b/src/QGCApplication.h index dc402e6f6..2300f4fa9 100644 --- a/src/QGCApplication.h +++ b/src/QGCApplication.h @@ -84,16 +84,6 @@ public: /// @brief Sets the flag to log all mavlink connections void setPromptFlightDataSave(bool promptForSave); - /// @brief All global singletons must be registered such that QGCApplication::destorySingletonsForUnitTest - /// can work correctly. - void registerSingleton(QGCSingleton* singleton); - - /// @brief Creates non-ui based singletons for unit testing - void createSingletonsForUnitTest(void) { _createSingletons(); } - - /// @brief Destroys all singletons. Used by unit test code to reset global state. - void destroySingletonsForUnitTest(void); - /// @brief Returns truee if unit test are being run bool runningUnitTests(void) { return _runningUnitTests; } @@ -114,6 +104,7 @@ public: private: void _createSingletons(void); + void _destroySingletons(void); static const char* _settingsVersionKey; ///< Settings key which hold settings version static const char* _deleteAllSettingsKey; ///< If this settings key is set on boot, all settings will be deleted @@ -124,9 +115,10 @@ private: static const char* _savedFileMavlinkLogDirectoryName; ///< Name of mavlink log subdirectory static const char* _savedFileParameterDirectoryName; ///< Name of parameter subdirectory - QList _singletons; ///< List of registered global singletons - bool _runningUnitTests; ///< true: running unit tests, false: normal app + + /// Unit Test have access to creating and destroying singletons + friend class UnitTest; }; /// @brief Returns the QGCApplication object singleton. diff --git a/src/QGCSingleton.cc b/src/QGCSingleton.cc index 6b4c98fc3..3149523f4 100644 --- a/src/QGCSingleton.cc +++ b/src/QGCSingleton.cc @@ -29,10 +29,8 @@ #include "QGCSingleton.h" #include "QGCApplication.h" -QGCSingleton::QGCSingleton(QObject* parent, bool registerSingleton) : +QGCSingleton::QGCSingleton(QObject* parent) : QObject(parent) { - if (registerSingleton) { - qgcApp()->registerSingleton(this); - } + } diff --git a/src/QGCSingleton.h b/src/QGCSingleton.h index b3975dd24..c0e5eac7d 100644 --- a/src/QGCSingleton.h +++ b/src/QGCSingleton.h @@ -22,30 +22,137 @@ ======================================================================*/ /// @file -/// @brief Base class for global singletons -/// /// @author Don Gagne #ifndef QGCSINGLETON_H #define QGCSINGLETON_H #include +#include + +/// @def DECLARE_QGC_SINGLETON +/// Include this macro in your Derived Class definition +/// @param className Derived Class name +/// @param interfaceName If your class is accessed through an interface specify that, if not specify Derived class name. +/// For example DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface) +#define DECLARE_QGC_SINGLETON(className, interfaceName) \ + public: \ + static interfaceName* instance(void); \ + static void setMockInstance(interfaceName* mock); \ + private: \ + static interfaceName* _createSingleton(void); \ + static void _deleteSingleton(void); \ + static interfaceName* _instance; \ + static interfaceName* _mockInstance; \ + static interfaceName* _realInstance; \ + friend class QGCApplication; \ + friend class UnitTest; \ + +/// @def IMPLEMENT_QGC_SINGLETON +/// Include this macro in your Derived Class implementation +/// @param className Derived Class name +/// @param interfaceName If your class is accessed through an interface specify that, if not specify Derived class name. +/// For example DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface) +#define IMPLEMENT_QGC_SINGLETON(className, interfaceName) \ + interfaceName* className::_instance = NULL; \ + interfaceName* className::_mockInstance = NULL; \ + interfaceName* className::_realInstance = NULL; \ + \ + interfaceName* className::_createSingleton(void) \ + { \ + Q_ASSERT(_instance == NULL); \ + _instance = new className(qgcApp()); \ + return _instance; \ + } \ + \ + void className::_deleteSingleton(void) \ + { \ + if (className::_instance) { \ + className* instance = qobject_cast(className::_instance); \ + Q_ASSERT_X(instance != NULL, "QGCSingleton", "If you hit this assert you may have forgotten to clear a Mock instance"); \ + className::_instance = NULL; \ + delete instance; \ + } \ + } \ + \ + interfaceName* className::instance(void) \ + { \ + Q_ASSERT_X(_instance, "QGCSingleton", "If you hit this, then you have run into a startup or shutdown sequence bug."); \ + return _instance; \ + } \ + \ + void className::setMockInstance(interfaceName* mock) \ + { \ + if (mock) { \ + Q_ASSERT(_instance); \ + Q_ASSERT(!_realInstance); \ + \ + _realInstance = _instance; \ + _instance = dynamic_cast(mock); \ + Q_ASSERT(_instance); \ + _mockInstance = mock; \ + } else { \ + Q_ASSERT(_instance); \ + Q_ASSERT(_realInstance); \ + \ + _instance = _realInstance; \ + _realInstance = NULL; \ + _mockInstance = NULL; \ + } \ + } + +class QGCApplication; +class UnitTest; -#include "QGCApplication.h" +/// This is the base class for all app global singletons +/// +/// All global singletons are created/destroyed at boot time by QGCApplication::_createSingletons and destroyed by QGC::Application::_destroySingletons. +/// This is done in order to make sure they are all created on the main thread. As such no other code other than Unit Test +/// code has access to the constructor/destructor. QGCSingleton supports replacing singletons with a mock implementation. +/// In this case your object must derive from an interface which in turn derives from QGCSingleton. Youu can then use +/// the setMock method to add and remove you mock implementation. See UASManager example usage. In order to provide the +/// appropriate methods to make all this work you need to use the DECLARE_QGC_SINGLETON and IMPLEMENT_QGC_SINGLETON +/// macros as follows: +/// @code{.unparsed} +/// // Header file +/// +/// class MySingleton : public QGCSingleton { +/// Q_OBJECT +/// +/// DECLARE_QGC_SINGLETON(MySingleton, MySingleton) +/// +/// ... +/// +/// private: +/// // Constructor/Desctructor private since all access is through the singleton methods +/// MySingleton(QObject* parent == NULL); +/// ~MySingleton(); +/// +/// ... +/// } +/// +/// // Code file +/// +/// IMPLEMENT_QGC_SINGLETON(MySingleton, MySingleton) +/// +/// MySingleton::MySingleton(QObject* parent) : +/// QGCSigleton(parent) +/// { +/// } +/// +/// // Other class methods... +/// +/// @endcode +/// The example above does use an inteface so the second parameter to the macro is the class name as well. class QGCSingleton : public QObject { Q_OBJECT -public: - /// @brief Contructor will register singleton to QGCApplication +protected: + /// Constructor is private since all creation is done through _createInstance /// @param parent Parent object - /// @param registerSingleton true: register with QGCApplication, false: do not register (only used for Mock implementations) - QGCSingleton(QObject* parent = NULL, bool registerSingleton = true); - - /// @brief Implementation should delete the singleton such that next call to instance - /// will create a new singleton. - virtual void deleteInstance(void) = 0; + QGCSingleton(QObject* parent = NULL); }; #endif diff --git a/src/comm/LinkManager.cc b/src/comm/LinkManager.cc index 6c5385199..ab954ef64 100644 --- a/src/comm/LinkManager.cc +++ b/src/comm/LinkManager.cc @@ -38,41 +38,18 @@ This file is part of the QGROUNDCONTROL project #include "QGCMessageBox.h" #include "QGCApplication.h" -LinkManager* LinkManager::_instance = NULL; - -LinkManager* LinkManager::instance(void) -{ - if(_instance == 0) { - new LinkManager(qgcApp()); - Q_CHECK_PTR(_instance); - } - - Q_ASSERT(_instance); - - return _instance; -} - -void LinkManager::deleteInstance(void) -{ - _instance = NULL; - delete this; -} +IMPLEMENT_QGC_SINGLETON(LinkManager, LinkManager) /** * @brief Private singleton constructor * * This class implements the singleton design pattern and has therefore only a private constructor. **/ -LinkManager::LinkManager(QObject* parent, bool registerSingleton) : - QGCSingleton(parent, registerSingleton), +LinkManager::LinkManager(QObject* parent) : + QGCSingleton(parent), _connectionsSuspended(false), _mavlink(NULL) { - if (registerSingleton) { - Q_ASSERT(_instance == NULL); - _instance = this; - } - _mavlink = new MAVLinkProtocol(this); Q_CHECK_PTR(_mavlink); } diff --git a/src/comm/LinkManager.h b/src/comm/LinkManager.h index b19f507d7..88a9eaf4e 100644 --- a/src/comm/LinkManager.h +++ b/src/comm/LinkManager.h @@ -49,14 +49,13 @@ class LinkManagerTest; class LinkManager : public QGCSingleton { Q_OBJECT - -public: - /// @brief Returns the LinkManager singleton - static LinkManager* instance(void); - virtual void deleteInstance(void); - - ~LinkManager(); + DECLARE_QGC_SINGLETON(LinkManager, LinkManager) + + /// Unit Test has access to private constructor/destructor + friend class LinkManagerTest; + +public: /// Returns list of all links const QList getLinks(); @@ -99,19 +98,15 @@ signals: private: /// All access to LinkManager is through LinkManager::instance - LinkManager(QObject* parent = NULL, bool registerSingleton = true); - - /// LinkManager unit test is allowed to new LinkManager objects - friend class LinkManagerTest; + LinkManager(QObject* parent = NULL); + ~LinkManager(); + bool _connectionsSuspendedMsg(void); - static LinkManager* _instance; /// LinkManager singleton - QList _links; ///< List of available links QMutex _linkListMutex; ///< Mutex for thread safe access to _links list - bool _connectionsSuspended; ///< true: all new connections should not be allowed QString _connectionsSuspendedReason; ///< User visible reason for suspension diff --git a/src/qgcunittest/LinkManagerTest.cc b/src/qgcunittest/LinkManagerTest.cc index f75f8c2b2..45c33811d 100644 --- a/src/qgcunittest/LinkManagerTest.cc +++ b/src/qgcunittest/LinkManagerTest.cc @@ -45,7 +45,7 @@ void LinkManagerTest::init(void) Q_ASSERT(_linkMgr == NULL); Q_ASSERT(_multiSpy == NULL); - _linkMgr = new LinkManager(NULL /* no parent */, false /* don't register singleton */); + _linkMgr = new LinkManager(NULL /* no parent */); Q_CHECK_PTR(_linkMgr); _rgSignals[newLinkSignalIndex] = SIGNAL(newLink(LinkInterface*)); @@ -57,8 +57,6 @@ void LinkManagerTest::init(void) void LinkManagerTest::cleanup(void) { - UnitTest::cleanup(); - Q_ASSERT(_linkMgr); Q_ASSERT(_multiSpy); @@ -67,18 +65,11 @@ void LinkManagerTest::cleanup(void) _linkMgr = NULL; _multiSpy = NULL; -} - - -void LinkManagerTest::_instance_test(void) -{ - LinkManager *linkManager = new LinkManager(NULL /* no parent */, false /* don't register singleton */); - // If the flag to not register singleton is not working this will cause QGCApplication to crash on - // desctrucion since it will try to de-reference a deleted singleton. - delete linkManager; + UnitTest::cleanup(); } + void LinkManagerTest::_add_test(void) { Q_ASSERT(_linkMgr); diff --git a/src/qgcunittest/LinkManagerTest.h b/src/qgcunittest/LinkManagerTest.h index 566c4885b..779265575 100644 --- a/src/qgcunittest/LinkManagerTest.h +++ b/src/qgcunittest/LinkManagerTest.h @@ -44,7 +44,6 @@ private slots: void init(void); void cleanup(void); - void _instance_test(void); void _add_test(void); void _delete_test(void); void _addSignals_test(void); diff --git a/src/qgcunittest/MavlinkLogTest.cc b/src/qgcunittest/MavlinkLogTest.cc index 9d6f79d1c..eed634fc5 100644 --- a/src/qgcunittest/MavlinkLogTest.cc +++ b/src/qgcunittest/MavlinkLogTest.cc @@ -59,12 +59,12 @@ void MavlinkLogTest::init(void) void MavlinkLogTest::cleanup(void) { - UnitTest::cleanup(); - // Make sure no left over logs in temp directory QDir tmpDir(QStandardPaths::writableLocation(QStandardPaths::TempLocation)); QStringList logFiles(tmpDir.entryList(QStringList(QString("*.%1").arg(_logFileExtension)), QDir::Files)); QCOMPARE(logFiles.count(), 0); + + UnitTest::cleanup(); } void MavlinkLogTest::_createTempLogFile(bool zeroLength) diff --git a/src/qgcunittest/MockUASManager.cc b/src/qgcunittest/MockUASManager.cc index aa8a09566..953dd9fc3 100644 --- a/src/qgcunittest/MockUASManager.cc +++ b/src/qgcunittest/MockUASManager.cc @@ -24,7 +24,7 @@ #include "MockUASManager.h" MockUASManager::MockUASManager(void) : - UASManagerInterface(NULL, false /* do not register singleton with QGCApplication */), + UASManagerInterface(NULL), _mockUAS(NULL) { diff --git a/src/qgcunittest/PX4RCCalibrationTest.cc b/src/qgcunittest/PX4RCCalibrationTest.cc index 793108a3f..a565aafbe 100644 --- a/src/qgcunittest/PX4RCCalibrationTest.cc +++ b/src/qgcunittest/PX4RCCalibrationTest.cc @@ -156,7 +156,7 @@ void PX4RCCalibrationTest::init(void) _mockUASManager = new MockUASManager(); Q_ASSERT(_mockUASManager); - UASManager::setMockUASManager(_mockUASManager); + UASManager::setMockInstance(_mockUASManager); _mockUAS = new MockUAS(); Q_CHECK_PTR(_mockUAS); @@ -201,19 +201,18 @@ void PX4RCCalibrationTest::init(void) void PX4RCCalibrationTest::cleanup(void) { - UnitTest::cleanup(); - Q_ASSERT(_calWidget); delete _calWidget; Q_ASSERT(_mockUAS); delete _mockUAS; - UASManager::setMockUASManager(NULL); + UASManager::setMockInstance(NULL); Q_ASSERT(_mockUASManager); delete _mockUASManager; + UnitTest::cleanup(); } /// @brief Test for correct behavior in determining minimum numbers of channels for flight. diff --git a/src/qgcunittest/QGCUASFileManagerTest.cc b/src/qgcunittest/QGCUASFileManagerTest.cc index 84134650a..ef48f8d47 100644 --- a/src/qgcunittest/QGCUASFileManagerTest.cc +++ b/src/qgcunittest/QGCUASFileManagerTest.cc @@ -88,8 +88,6 @@ void QGCUASFileManagerUnitTest::init(void) // Called after every test case void QGCUASFileManagerUnitTest::cleanup(void) { - UnitTest::cleanup(); - Q_ASSERT(_multiSpy); Q_ASSERT(_fileManager); @@ -98,6 +96,8 @@ void QGCUASFileManagerUnitTest::cleanup(void) _fileManager = NULL; _multiSpy = NULL; + + UnitTest::cleanup(); } /// @brief Connected to QGCUASFileManager listEntry signal in order to catch list entries diff --git a/src/qgcunittest/TCPLinkTest.cc b/src/qgcunittest/TCPLinkTest.cc index 6126f9c0a..86dde4e3c 100644 --- a/src/qgcunittest/TCPLinkTest.cc +++ b/src/qgcunittest/TCPLinkTest.cc @@ -68,8 +68,6 @@ void TCPLinkUnitTest::init(void) // Called after every test void TCPLinkUnitTest::cleanup(void) { - UnitTest::cleanup(); - Q_ASSERT(_multiSpy); Q_ASSERT(_link); @@ -78,6 +76,8 @@ void TCPLinkUnitTest::cleanup(void) _multiSpy = NULL; _link = NULL; + + UnitTest::cleanup(); } void TCPLinkUnitTest::_properties_test(void) diff --git a/src/qgcunittest/UASUnitTest.cc b/src/qgcunittest/UASUnitTest.cc index 594b8b239..8b2991f51 100644 --- a/src/qgcunittest/UASUnitTest.cc +++ b/src/qgcunittest/UASUnitTest.cc @@ -20,13 +20,13 @@ void UASUnitTest::init() //this function is called after every test void UASUnitTest::cleanup() { - UnitTest::cleanup(); - delete _uas; _uas = NULL; delete _mavlink; _mavlink = NULL; + + UnitTest::cleanup(); } void UASUnitTest::getUASID_test() diff --git a/src/qgcunittest/UnitTest.cc b/src/qgcunittest/UnitTest.cc index f0d25008c..c3ac1fa91 100644 --- a/src/qgcunittest/UnitTest.cc +++ b/src/qgcunittest/UnitTest.cc @@ -114,8 +114,8 @@ void UnitTest::init(void) _expectMissedMessageBox = false; // Each test gets a clean global state - qgcApp()->destroySingletonsForUnitTest(); - qgcApp()->createSingletonsForUnitTest(); + qgcApp()->_destroySingletons(); + qgcApp()->_createSingletons(); MAVLinkProtocol::deleteTempLogFiles(); } @@ -136,7 +136,7 @@ void UnitTest::cleanup(void) } QCOMPARE(_missedFileDialogCount, 0); - qgcApp()->destroySingletonsForUnitTest(); + qgcApp()->_destroySingletons(); } void UnitTest::setExpectedMessageBox(QMessageBox::StandardButton response) diff --git a/src/uas/UASManager.cc b/src/uas/UASManager.cc index 57ca620d5..ffb41c36a 100644 --- a/src/uas/UASManager.cc +++ b/src/uas/UASManager.cc @@ -24,35 +24,29 @@ #define MEAN_EARTH_DIAMETER 12756274.0 #define UMR 0.017453292519943295769236907684886 -UASManager* UASManager::_instance = NULL; -UASManagerInterface* UASManager::_mockUASManager = NULL; +IMPLEMENT_QGC_SINGLETON(UASManager, UASManagerInterface) - -void UASManager::setMockUASManager(UASManagerInterface* mockUASManager) +UASManager::UASManager(QObject* parent) : + UASManagerInterface(parent), + activeUAS(NULL), + offlineUASWaypointManager(NULL), + homeLat(47.3769), + homeLon(8.549444), + homeAlt(470.0), + homeFrame(MAV_FRAME_GLOBAL) { - _mockUASManager = mockUASManager; + loadSettings(); + setLocalNEDSafetyBorders(1, -1, 0, -1, 1, -1); } -UASManagerInterface* UASManager::instance() +UASManager::~UASManager() { - if (_mockUASManager) { - return _mockUASManager; - } - - if(_instance == NULL) { - _instance = new UASManager(qgcApp()); - Q_CHECK_PTR(_instance); + storeSettings(); + // Delete all systems + foreach (UASInterface* mav, systems) { + // deleteLater so it ends up on correct thread + mav->deleteLater(); } - - Q_ASSERT(_instance); - - return _instance; -} - -void UASManager::deleteInstance(void) -{ - _instance = NULL; - delete this; } void UASManager::storeSettings() @@ -256,34 +250,6 @@ void UASManager::uavChangedHomePosition(int uav, double lat, double lon, double } } -/** - * @brief Private singleton constructor - * - * This class implements the singleton design pattern and has therefore only a private constructor. - **/ -UASManager::UASManager(QObject* parent) : - UASManagerInterface(parent), - activeUAS(NULL), - offlineUASWaypointManager(NULL), - homeLat(47.3769), - homeLon(8.549444), - homeAlt(470.0), - homeFrame(MAV_FRAME_GLOBAL) -{ - loadSettings(); - setLocalNEDSafetyBorders(1, -1, 0, -1, 1, -1); -} - -UASManager::~UASManager() -{ - storeSettings(); - // Delete all systems - foreach (UASInterface* mav, systems) { - // deleteLater so it ends up on correct thread - mav->deleteLater(); - } -} - void UASManager::addUAS(UASInterface* uas) { // WARNING: The active uas is set here diff --git a/src/uas/UASManager.h b/src/uas/UASManager.h index b79fb8d1a..65ea09924 100644 --- a/src/uas/UASManager.h +++ b/src/uas/UASManager.h @@ -38,7 +38,7 @@ This file is part of the QGROUNDCONTROL project #include #include "../../libs/eigen/Eigen/Eigen" #include "QGCGeo.h" -#include "QGCApplication.h" +#include "QGCSingleton.h" /** * @brief Central manager for all connected aerial vehicles @@ -49,20 +49,10 @@ This file is part of the QGROUNDCONTROL project class UASManager : public UASManagerInterface { Q_OBJECT - -public: - /// @brief Returns the UASManager singleton - static UASManagerInterface* instance(void); - - virtual void deleteInstance(void); - - ~UASManager(); - /** - * @brief Sets a mock UASManager to be returned when a call is made to instance() - **/ - static void setMockUASManager(UASManagerInterface* mockUASManager); + DECLARE_QGC_SINGLETON(UASManager, UASManagerInterface) +public: /** * @brief Get the currently selected UAS * @@ -273,9 +263,7 @@ private: /// @brief All access to UASManager singleton is through UASManager::instance UASManager(QObject* parent = NULL); - static UASManager* _instance; - - static UASManagerInterface* _mockUASManager; + ~UASManager(); public: /* Need to align struct pointer to prevent a memory assertion: diff --git a/src/uas/UASManagerInterface.h b/src/uas/UASManagerInterface.h index 6b49af394..83619396b 100644 --- a/src/uas/UASManagerInterface.h +++ b/src/uas/UASManagerInterface.h @@ -57,11 +57,6 @@ class UASManagerInterface : public QGCSingleton Q_OBJECT public: - /// @brief Contructor will register singleton to QGCApplication - /// @param parent Parent object - /// @param registerSingleton true: register with QGCApplication, false: do not register (only used for Mock implementations) - UASManagerInterface(QObject* parent = NULL, bool registerSingleton = true) : QGCSingleton(parent, registerSingleton) { } - virtual UASInterface* getActiveUAS() = 0; virtual UASWaypointManager *getActiveUASWaypointManager() = 0; virtual UASInterface* silentGetActiveUAS() = 0; @@ -112,6 +107,11 @@ signals: void activeUASStatusChanged(int systemId, bool active); /** @brief Current home position changed */ void homePositionChanged(double lat, double lon, double alt); + +protected: + // FIXME: Do we need this here? + UASManagerInterface(QObject* parent = NULL) : + QGCSingleton(parent) { } }; #endif // _UASMANAGERINTERFACE_H_ -- 2.22.0