diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index d176cc50448..fc8bd35e4b0 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -8,7 +8,6 @@ #include "optionsparser.h" #include "pluginmanager_p.h" #include "pluginspec.h" -#include "shutdownguard.h" #include @@ -21,6 +20,7 @@ #include #include #include +#include #include #include @@ -248,26 +248,6 @@ using namespace Internal; static Internal::PluginManagerPrivate *d = nullptr; static PluginManager *m_instance = nullptr; -static QObject *m_shutdownGuard = nullptr; - -/*! - Returns an object that can be used as the parent for objects that should be - destroyed just at the end of the applications lifetime. - The object is destroyed after all plugins' aboutToShutdown methods - have finished, just before the plugins are deleted. - - Only use this from the application's main thread. - - \sa ExtensionSystem::IPlugin::aboutToShutdown() -*/ -QObject *shutdownGuard() -{ - if (!m_shutdownGuard) { - QTC_CHECK(Utils::isMainThread()); - m_shutdownGuard = new QObject; - } - return m_shutdownGuard; -} /*! Gets the unique plugin manager instance. @@ -1092,8 +1072,7 @@ void PluginManagerPrivate::deleteAll() Utils::futureSynchronizer()->isCancelOnWait(), Utils::futureSynchronizer()->cancelAllFutures()); Utils::futureSynchronizer()->waitForFinished(); // Synchronize all futures from all plugins - delete m_shutdownGuard; - m_shutdownGuard = nullptr; + triggerShutdownGuard(); Utils::reverseForeach(loadQueue(), [this](PluginSpec *spec) { loadPlugin(spec, PluginSpec::Deleted); }); diff --git a/src/libs/utils/CMakeLists.txt b/src/libs/utils/CMakeLists.txt index f048fd5a061..f1f83d9b7e3 100644 --- a/src/libs/utils/CMakeLists.txt +++ b/src/libs/utils/CMakeLists.txt @@ -150,6 +150,7 @@ add_qtc_library(Utils set_algorithm.h settingsaccessor.cpp settingsaccessor.h settingsselector.cpp settingsselector.h + shutdownguard.cpp shutdownguard.h sizedarray.h smallstring.h smallstringfwd.h diff --git a/src/libs/utils/shutdownguard.cpp b/src/libs/utils/shutdownguard.cpp new file mode 100644 index 00000000000..4fbef5834f0 --- /dev/null +++ b/src/libs/utils/shutdownguard.cpp @@ -0,0 +1,73 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR GPL-3.0-only WITH Qt-GPL-exception-1.0 + +#include + +#include +#include + +namespace Utils { + +class ShutdownGuardHolder final +{ +public: + ~ShutdownGuardHolder() + { + if (!m_alreadyGone) + triggerShutdownGuard(); + } + + QObject *shutdownGuard() + { + QTC_CHECK(!m_alreadyGone); + if (!m_shutdownGuard) { + QTC_CHECK(Utils::isMainThread()); + m_shutdownGuard = new QObject; + } + return m_shutdownGuard; + } + + void triggerShutdownGuard() + { + m_alreadyGone = true; + delete m_shutdownGuard; + m_shutdownGuard = nullptr; + } + +private: + QObject *m_shutdownGuard = nullptr; + bool m_alreadyGone = false; +}; + +static ShutdownGuardHolder theShutdownGuardHolder; + +/*! + Destroys the shutdown guard object and consequently all + objects guarded by it. + + In a normal run of the application this function is called + automatically at the appropriate time. +*/ + +void triggerShutdownGuard() +{ + return theShutdownGuardHolder.triggerShutdownGuard(); +} + +/*! + Returns an object that can be used as the parent for objects that should be + destroyed just at the end of the applications lifetime. + The object is destroyed after all plugins' aboutToShutdown methods + have finished, just before the plugins are deleted. + + Only use this from the application's main thread. + + \sa ExtensionSystem::IPlugin::aboutToShutdown() +*/ + +QObject *shutdownGuard() +{ + return theShutdownGuardHolder.shutdownGuard(); +} + +} // Utils diff --git a/src/libs/extensionsystem/shutdownguard.h b/src/libs/utils/shutdownguard.h similarity index 71% rename from src/libs/extensionsystem/shutdownguard.h rename to src/libs/utils/shutdownguard.h index 63f32f88eca..226bd06d76c 100644 --- a/src/libs/extensionsystem/shutdownguard.h +++ b/src/libs/utils/shutdownguard.h @@ -3,13 +3,16 @@ #pragma once -#include "extensionsystem_global.h" +#include "utils_global.h" #include -namespace ExtensionSystem { +namespace Utils { -EXTENSIONSYSTEM_EXPORT QObject *shutdownGuard(); +QTCREATOR_UTILS_EXPORT QObject *shutdownGuard(); + +// Called from PluginManagerPrivate::deleteAll() +QTCREATOR_UTILS_EXPORT void triggerShutdownGuard(); template class GuardedObject @@ -31,4 +34,4 @@ private: T *m_object; }; -} // namespace ExtensionSystem +} // namespace Utils diff --git a/src/libs/utils/utils.qbs b/src/libs/utils/utils.qbs index f08279ab043..fa9d611d5c9 100644 --- a/src/libs/utils/utils.qbs +++ b/src/libs/utils/utils.qbs @@ -271,6 +271,8 @@ QtcLibrary { "result.h", "savefile.cpp", "savefile.h", + "shutdownguard.cpp", + "shutdownguard.h", "scopedswap.h", "scopedtimer.cpp", "scopedtimer.h", diff --git a/src/plugins/coreplugin/messagemanager.cpp b/src/plugins/coreplugin/messagemanager.cpp index f74defc51bd..ea2dea1ed5d 100644 --- a/src/plugins/coreplugin/messagemanager.cpp +++ b/src/plugins/coreplugin/messagemanager.cpp @@ -9,9 +9,8 @@ #include "ioutputpane.h" #include "outputwindow.h" -#include - #include +#include #include #include @@ -100,7 +99,7 @@ private: static MessageOutputWindow *messageOutputWindow() { static QPointer theMessageOutputWindow - = new MessageOutputWindow(ExtensionSystem::shutdownGuard()); + = new MessageOutputWindow(Utils::shutdownGuard()); return theMessageOutputWindow.get(); } @@ -124,7 +123,7 @@ static void showOutputPane(Flag flags) static void writeImpl(const QString &text, Flag flags) { // Make sure this end up in the GUI thread. - QMetaObject::invokeMethod(ExtensionSystem::shutdownGuard(), [text, flags] { + QMetaObject::invokeMethod(Utils::shutdownGuard(), [text, flags] { QTC_ASSERT(messageOutputWindow(), return); showOutputPane(flags); messageOutputWindow()->append(text + '\n'); diff --git a/src/plugins/coreplugin/session.cpp b/src/plugins/coreplugin/session.cpp index d5c33d15b23..a174ddeec52 100644 --- a/src/plugins/coreplugin/session.cpp +++ b/src/plugins/coreplugin/session.cpp @@ -17,7 +17,6 @@ #include #include -#include #include #include @@ -27,6 +26,7 @@ #include #include #include +#include #include #include @@ -114,7 +114,7 @@ static SessionManagerPrivate *d = nullptr; SessionManager *sessionManager() { - static ExtensionSystem::GuardedObject theSessionManager; + static GuardedObject theSessionManager; return theSessionManager.get(); } diff --git a/src/plugins/ios/iosdevice.cpp b/src/plugins/ios/iosdevice.cpp index b042ebe46f6..76b7c4911e3 100644 --- a/src/plugins/ios/iosdevice.cpp +++ b/src/plugins/ios/iosdevice.cpp @@ -13,8 +13,6 @@ #include #include -#include - #include #include #include @@ -23,6 +21,7 @@ #include #include #include +#include #include @@ -628,7 +627,7 @@ void IosDeviceManager::updateUserModeDevices() IosDeviceManager *IosDeviceManager::instance() { - static IosDeviceManager *theInstance = new IosDeviceManager(ExtensionSystem::shutdownGuard()); + static IosDeviceManager *theInstance = new IosDeviceManager(Utils::shutdownGuard()); return theInstance; } diff --git a/src/plugins/vcsbase/vcsbaseclient.cpp b/src/plugins/vcsbase/vcsbaseclient.cpp index a57d3014ce5..910787ad7bd 100644 --- a/src/plugins/vcsbase/vcsbaseclient.cpp +++ b/src/plugins/vcsbase/vcsbaseclient.cpp @@ -16,14 +16,13 @@ #include #include -#include - #include #include #include #include #include +#include #include #include @@ -213,7 +212,7 @@ VcsCommand *VcsBaseClientImpl::createVcsCommand(const FilePath &defaultWorkingDi const Environment &environment) { auto command = new VcsCommand(defaultWorkingDir, environment); - command->setParent(ExtensionSystem::shutdownGuard()); + command->setParent(Utils::shutdownGuard()); return command; }