From de290e03419f9a548b564f1c80a2b9cad142f11e Mon Sep 17 00:00:00 2001 From: Eike Ziller <eike.ziller@nokia.com> Date: Thu, 2 Feb 2012 10:47:33 +0100 Subject: [PATCH] Add "delayedInitialize" feature to plugin manager. And use it for some of the plugins. It avoids the plugins to do the timing on their own, and actually adds guarantees about the order the delayed initialization is done. Change-Id: I88ad9b46b24b82c91509774170fe0e7e99e88e4b Reviewed-by: Tobias Hunger <tobias.hunger@nokia.com> --- src/libs/extensionsystem/iplugin.cpp | 23 +++++++++++++ src/libs/extensionsystem/iplugin.h | 1 + src/libs/extensionsystem/pluginmanager.cpp | 38 +++++++++++++++++++++- src/libs/extensionsystem/pluginmanager_p.h | 6 ++++ src/libs/extensionsystem/pluginspec.cpp | 19 +++++++++++ src/libs/extensionsystem/pluginspec_p.h | 1 + src/plugins/coreplugin/coreplugin.cpp | 13 ++++++-- src/plugins/coreplugin/coreplugin.h | 9 ++--- src/plugins/coreplugin/helpmanager.cpp | 7 ---- src/plugins/coreplugin/helpmanager.h | 10 +++--- src/plugins/locator/locatorplugin.cpp | 4 +-- src/plugins/locator/locatorplugin.h | 2 +- src/plugins/qtsupport/qtsupportplugin.cpp | 4 +++ src/plugins/qtsupport/qtsupportplugin.h | 1 + src/plugins/qtsupport/qtversionmanager.cpp | 12 +++---- src/plugins/qtsupport/qtversionmanager.h | 6 ++-- 16 files changed, 124 insertions(+), 32 deletions(-) diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 5060b0a68d6..e6ee6e4a6b9 100644 --- a/src/libs/extensionsystem/iplugin.cpp +++ b/src/libs/extensionsystem/iplugin.cpp @@ -98,6 +98,7 @@ describing the reason. \sa extensionsInitialized() + \sa delayedInitialize() */ /*! @@ -112,6 +113,28 @@ been provided by dependent plugins. \sa initialize() + \sa delayedInitialize() +*/ + +/*! + \fn bool IPlugin::delayedInitialize() + \brief Called after all plugins' IPlugin::extensionsInitialized() method has been called, + and after the IPlugin::delayedInitialize() method of plugins that depend on this plugin + have been called. + + The plugins' delayedInitialize() methods are called after the application is already running, + with a few milliseconds delay to application startup, and between individual delayedInitialize + method calls. To avoid unnecessary delays, a plugin should return true from the method if it + actually implements it, to indicate that the next plugins' delayedInitialize() call should + be delayed a few milliseconds to give input and paint events a chance to be processed. + + This method can be used if a plugin needs to do non-trivial setup that doesn't + necessarily needs to be done directly at startup, but still should be done within a + short time afterwards. This can increase the felt plugin/application startup + time a lot, with very little effort. + + \sa initialize() + \sa extensionsInitialized() */ /*! diff --git a/src/libs/extensionsystem/iplugin.h b/src/libs/extensionsystem/iplugin.h index b3652aed3f3..8d251820fd2 100644 --- a/src/libs/extensionsystem/iplugin.h +++ b/src/libs/extensionsystem/iplugin.h @@ -62,6 +62,7 @@ public: virtual bool initialize(const QStringList &arguments, QString *errorString) = 0; virtual void extensionsInitialized() = 0; + virtual bool delayedInitialize() { return false; } virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; } virtual void remoteCommand(const QStringList & /* options */, const QStringList & /* arguments */) { } diff --git a/src/libs/extensionsystem/pluginmanager.cpp b/src/libs/extensionsystem/pluginmanager.cpp index 7d19c9ffbee..9420af85b46 100644 --- a/src/libs/extensionsystem/pluginmanager.cpp +++ b/src/libs/extensionsystem/pluginmanager.cpp @@ -55,6 +55,7 @@ static const char C_IGNORED_PLUGINS[] = "Plugins/Ignored"; static const char C_FORCEENABLED_PLUGINS[] = "Plugins/ForceEnabled"; +static const int DELAYED_INITIALIZE_INTERVAL = 20; // ms typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet; @@ -782,12 +783,32 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec) return spec->d; } +void PluginManagerPrivate::nextDelayedInitialize() +{ + while (!delayedInitializeQueue.isEmpty()) { + PluginSpec *spec = delayedInitializeQueue.takeFirst(); + profilingReport(">delayedInitialize", spec); + bool delay = spec->d->delayedInitialize(); + profilingReport("<delayedInitialize", spec); + if (delay) + break; // do next delayedInitialize after a delay + } + if (delayedInitializeQueue.isEmpty()) { + delete delayedInitializeTimer; + delayedInitializeTimer = 0; + } else { + delayedInitializeTimer->start(); + } +} + /*! \fn PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) \internal */ PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) : extension(QLatin1String("xml")), + delayedInitializeTimer(0), + shutdownEventLoop(0), m_profileElapsedMS(0), m_profilingVerbosity(0), settings(0), @@ -849,6 +870,11 @@ void PluginManagerPrivate::readSettings() */ void PluginManagerPrivate::stopAll() { + if (delayedInitializeTimer && delayedInitializeTimer->isActive()) { + delayedInitializeTimer->stop(); + delete delayedInitializeTimer; + delayedInitializeTimer = 0; + } QList<PluginSpec *> queue = loadQueue(); foreach (PluginSpec *spec, queue) { loadPlugin(spec, PluginSpec::Stopped); @@ -941,9 +967,19 @@ void PluginManagerPrivate::loadPlugins() QListIterator<PluginSpec *> it(queue); it.toBack(); while (it.hasPrevious()) { - loadPlugin(it.previous(), PluginSpec::Running); + PluginSpec *spec = it.previous(); + loadPlugin(spec, PluginSpec::Running); + if (spec->state() == PluginSpec::Running) + delayedInitializeQueue.append(spec); } emit q->pluginsChanged(); + + delayedInitializeTimer = new QTimer; + delayedInitializeTimer->setInterval(DELAYED_INITIALIZE_INTERVAL); + delayedInitializeTimer->setSingleShot(true); + connect(delayedInitializeTimer, SIGNAL(timeout()), + this, SLOT(nextDelayedInitialize())); + delayedInitializeTimer->start(); } /*! diff --git a/src/libs/extensionsystem/pluginmanager_p.h b/src/libs/extensionsystem/pluginmanager_p.h index 95f1db47c04..be33e8ad793 100644 --- a/src/libs/extensionsystem/pluginmanager_p.h +++ b/src/libs/extensionsystem/pluginmanager_p.h @@ -42,6 +42,7 @@ QT_BEGIN_NAMESPACE class QTime; +class QTimer; class QSettings; class QEventLoop; QT_END_NAMESPACE @@ -90,6 +91,10 @@ public: QStringList defaultDisabledPlugins; QStringList disabledPlugins; QStringList forceEnabledPlugins; + // delayed initialization + QTimer *delayedInitializeTimer; + QList<PluginSpec *> delayedInitializeQueue; + // ansynchronous shutdown QList<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown QEventLoop *shutdownEventLoop; // used for async shutdown @@ -109,6 +114,7 @@ public: static PluginSpecPrivate *privateSpec(PluginSpec *spec); private slots: + void nextDelayedInitialize(); void asyncShutdownFinished(); private: diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index eed4413b952..57c58992037 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -1013,6 +1013,25 @@ bool PluginSpecPrivate::initializeExtensions() return true; } +/*! + \fn bool PluginSpecPrivate::delayedInitialize() + \internal +*/ +bool PluginSpecPrivate::delayedInitialize() +{ + if (hasError) + return false; + if (state != PluginSpec::Running) { + return false; + } + if (!plugin) { + errorString = QCoreApplication::translate("PluginSpec", "Internal error: have no plugin instance to perform delayedInitialize"); + hasError = true; + return false; + } + return plugin->delayedInitialize(); +} + /*! \fn bool PluginSpecPrivate::stop() \internal diff --git a/src/libs/extensionsystem/pluginspec_p.h b/src/libs/extensionsystem/pluginspec_p.h index 25842ad563c..2ae53438e18 100644 --- a/src/libs/extensionsystem/pluginspec_p.h +++ b/src/libs/extensionsystem/pluginspec_p.h @@ -60,6 +60,7 @@ public: bool loadLibrary(); bool initializePlugin(); bool initializeExtensions(); + bool delayedInitialize(); IPlugin::ShutdownFlag stop(); void kill(); diff --git a/src/plugins/coreplugin/coreplugin.cpp b/src/plugins/coreplugin/coreplugin.cpp index 85d49a94788..3fe8bd19322 100644 --- a/src/plugins/coreplugin/coreplugin.cpp +++ b/src/plugins/coreplugin/coreplugin.cpp @@ -31,13 +31,14 @@ **************************************************************************/ #include "coreplugin.h" +#include "designmode.h" #include "editmode.h" #include "editormanager.h" -#include "mainwindow.h" -#include "modemanager.h" #include "fileiconprovider.h" -#include "designmode.h" +#include "helpmanager.h" +#include "mainwindow.h" #include "mimedatabase.h" +#include "modemanager.h" #include <extensionsystem/pluginmanager.h> @@ -105,6 +106,12 @@ void CorePlugin::extensionsInitialized() m_mainWindow->extensionsInitialized(); } +bool CorePlugin::delayedInitialize() +{ + HelpManager::instance()->setupHelpManager(); + return true; +} + void CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args) { m_mainWindow->openFiles(args, ICore::SwitchMode); diff --git a/src/plugins/coreplugin/coreplugin.h b/src/plugins/coreplugin/coreplugin.h index b3f27a2bd98..947abf800f6 100644 --- a/src/plugins/coreplugin/coreplugin.h +++ b/src/plugins/coreplugin/coreplugin.h @@ -50,10 +50,11 @@ public: CorePlugin(); ~CorePlugin(); - virtual bool initialize(const QStringList &arguments, QString *errorMessage = 0); - virtual void extensionsInitialized(); - virtual ShutdownFlag aboutToShutdown(); - virtual void remoteCommand(const QStringList & /* options */, const QStringList &args); + bool initialize(const QStringList &arguments, QString *errorMessage = 0); + void extensionsInitialized(); + bool delayedInitialize(); + ShutdownFlag aboutToShutdown(); + void remoteCommand(const QStringList & /* options */, const QStringList &args); public slots: void fileOpenRequest(const QString&); diff --git a/src/plugins/coreplugin/helpmanager.cpp b/src/plugins/coreplugin/helpmanager.cpp index f32032488ba..7f54267e0b0 100644 --- a/src/plugins/coreplugin/helpmanager.cpp +++ b/src/plugins/coreplugin/helpmanager.cpp @@ -40,7 +40,6 @@ #include <QtCore/QDir> #include <QtCore/QFileInfo> #include <QtCore/QStringList> -#include <QtCore/QTimer> #include <QtHelp/QHelpEngineCore> @@ -91,7 +90,6 @@ HelpManager::HelpManager(QObject *parent) : { Q_ASSERT(!m_instance); m_instance = this; - connect(Core::ICore::instance(), SIGNAL(coreOpened()), SLOT(delayedSetupHelpManager())); } HelpManager::~HelpManager() @@ -102,11 +100,6 @@ HelpManager::~HelpManager() delete d; } -void HelpManager::delayedSetupHelpManager() -{ - QTimer::singleShot(100, this, SLOT(setupHelpManager())); -} - HelpManager *HelpManager::instance() { Q_ASSERT(m_instance); diff --git a/src/plugins/coreplugin/helpmanager.h b/src/plugins/coreplugin/helpmanager.h index f72faa5d20e..90924ae52eb 100644 --- a/src/plugins/coreplugin/helpmanager.h +++ b/src/plugins/coreplugin/helpmanager.h @@ -46,6 +46,10 @@ QT_FORWARD_DECLARE_CLASS(QUrl) namespace Core { struct HelpManagerPrivate; +namespace Internal { +class CorePlugin; +} + class CORE_EXPORT HelpManager : public QObject { Q_OBJECT @@ -91,13 +95,11 @@ signals: void collectionFileChanged(); void helpRequested(const QUrl &url); -private slots: - void delayedSetupHelpManager(); - void setupHelpManager(); - private: + void setupHelpManager(); void verifyDocumenation(); HelpManagerPrivate *d; + friend class Internal::CorePlugin; // setupHelpManager }; } // Core diff --git a/src/plugins/locator/locatorplugin.cpp b/src/plugins/locator/locatorplugin.cpp index 9291901635d..868135e3d1c 100644 --- a/src/plugins/locator/locatorplugin.cpp +++ b/src/plugins/locator/locatorplugin.cpp @@ -139,7 +139,6 @@ bool LocatorPlugin::initialize(const QStringList &, QString *) addAutoReleasedObject(new LocatorFiltersFilter(this, m_locatorWidget)); - connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(startSettingsLoad())); return true; } @@ -167,10 +166,11 @@ void LocatorPlugin::extensionsInitialized() setFilters(m_filters); } -void LocatorPlugin::startSettingsLoad() +bool LocatorPlugin::delayedInitialize() { connect(&m_loadWatcher, SIGNAL(finished()), this, SLOT(settingsLoaded())); m_loadWatcher.setFuture(QtConcurrent::run(this, &LocatorPlugin::loadSettings)); + return true; } void LocatorPlugin::loadSettings() diff --git a/src/plugins/locator/locatorplugin.h b/src/plugins/locator/locatorplugin.h index 09e6e140b21..59ca5164449 100644 --- a/src/plugins/locator/locatorplugin.h +++ b/src/plugins/locator/locatorplugin.h @@ -63,6 +63,7 @@ public: bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); + bool delayedInitialize(); QList<ILocatorFilter*> filters(); QList<ILocatorFilter*> customFilters(); @@ -77,7 +78,6 @@ public slots: void openLocator(); private slots: - void startSettingsLoad(); void settingsLoaded(); void updatePlaceholderText(Core::Command *command = 0); diff --git a/src/plugins/qtsupport/qtsupportplugin.cpp b/src/plugins/qtsupport/qtsupportplugin.cpp index 84a19b1d724..21426016ded 100644 --- a/src/plugins/qtsupport/qtsupportplugin.cpp +++ b/src/plugins/qtsupport/qtsupportplugin.cpp @@ -80,7 +80,11 @@ bool QtSupportPlugin::initialize(const QStringList &arguments, QString *errorMes void QtSupportPlugin::extensionsInitialized() { QtVersionManager::instance()->extensionsInitialized(); +} +bool QtSupportPlugin::delayedInitialize() +{ + return QtVersionManager::instance()->delayedInitialize(); } Q_EXPORT_PLUGIN(QtSupportPlugin) diff --git a/src/plugins/qtsupport/qtsupportplugin.h b/src/plugins/qtsupport/qtsupportplugin.h index 12726fda01f..8ea327febde 100644 --- a/src/plugins/qtsupport/qtsupportplugin.h +++ b/src/plugins/qtsupport/qtsupportplugin.h @@ -49,6 +49,7 @@ class QtSupportPlugin : public ExtensionSystem::IPlugin public: bool initialize(const QStringList &arguments, QString *errorMessage); void extensionsInitialized(); + bool delayedInitialize(); private slots: #ifdef WITH_TESTS diff --git a/src/plugins/qtsupport/qtversionmanager.cpp b/src/plugins/qtsupport/qtversionmanager.cpp index bb8242ca77e..757cc131afe 100644 --- a/src/plugins/qtsupport/qtversionmanager.cpp +++ b/src/plugins/qtsupport/qtversionmanager.cpp @@ -138,10 +138,15 @@ void QtVersionManager::extensionsInitialized() findSystemQt(); } - connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(delayedUpdateDocumentation())); saveQtVersions(); } +bool QtVersionManager::delayedInitialize() +{ + updateDocumentation(); + return true; +} + QtVersionManager::~QtVersionManager() { qDeleteAll(m_versions); @@ -513,11 +518,6 @@ void QtVersionManager::updateDumpFor(const Utils::FileName &qmakeCommand) emit dumpUpdatedFor(qmakeCommand); } -void QtVersionManager::delayedUpdateDocumentation() -{ - QTimer::singleShot(100, this, SLOT(updateDocumentation())); -} - int QtVersionManager::getUniqueId() { return m_idcount++; diff --git a/src/plugins/qtsupport/qtversionmanager.h b/src/plugins/qtsupport/qtversionmanager.h index 611d82f379f..97690293adb 100644 --- a/src/plugins/qtsupport/qtversionmanager.h +++ b/src/plugins/qtsupport/qtversionmanager.h @@ -62,6 +62,7 @@ public: QtVersionManager(); ~QtVersionManager(); void extensionsInitialized(); + bool delayedInitialize(); // This will *always* return at least one (Qt in Path), even if that is // unconfigured. @@ -110,10 +111,6 @@ signals: public slots: void updateDumpFor(const Utils::FileName &qmakeCommand); -private slots: - void delayedUpdateDocumentation(); - void updateDocumentation(); - private: // This function is really simplistic... static bool equals(BaseQtVersion *a, BaseQtVersion *b); @@ -130,6 +127,7 @@ private: void findSystemQt(); void updateFromInstaller(); void saveQtVersions(); + void updateDocumentation(); // Used by QtOptionsPage void setNewQtVersions(QList<BaseQtVersion *> newVersions); // Used by QtVersion -- GitLab