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>
This commit is contained in:
Eike Ziller
2012-02-02 10:47:33 +01:00
parent 8a25c5352b
commit de290e0341
16 changed files with 124 additions and 32 deletions

View File

@@ -98,6 +98,7 @@
describing the reason. describing the reason.
\sa extensionsInitialized() \sa extensionsInitialized()
\sa delayedInitialize()
*/ */
/*! /*!
@@ -112,6 +113,28 @@
been provided by dependent plugins. been provided by dependent plugins.
\sa initialize() \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()
*/ */
/*! /*!

View File

@@ -62,6 +62,7 @@ public:
virtual bool initialize(const QStringList &arguments, QString *errorString) = 0; virtual bool initialize(const QStringList &arguments, QString *errorString) = 0;
virtual void extensionsInitialized() = 0; virtual void extensionsInitialized() = 0;
virtual bool delayedInitialize() { return false; }
virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; } virtual ShutdownFlag aboutToShutdown() { return SynchronousShutdown; }
virtual void remoteCommand(const QStringList & /* options */, const QStringList & /* arguments */) { } virtual void remoteCommand(const QStringList & /* options */, const QStringList & /* arguments */) { }

View File

@@ -55,6 +55,7 @@
static const char C_IGNORED_PLUGINS[] = "Plugins/Ignored"; static const char C_IGNORED_PLUGINS[] = "Plugins/Ignored";
static const char C_FORCEENABLED_PLUGINS[] = "Plugins/ForceEnabled"; static const char C_FORCEENABLED_PLUGINS[] = "Plugins/ForceEnabled";
static const int DELAYED_INITIALIZE_INTERVAL = 20; // ms
typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet; typedef QList<ExtensionSystem::PluginSpec *> PluginSpecSet;
@@ -782,12 +783,32 @@ PluginSpecPrivate *PluginManagerPrivate::privateSpec(PluginSpec *spec)
return spec->d; 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) \fn PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager)
\internal \internal
*/ */
PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) : PluginManagerPrivate::PluginManagerPrivate(PluginManager *pluginManager) :
extension(QLatin1String("xml")), extension(QLatin1String("xml")),
delayedInitializeTimer(0),
shutdownEventLoop(0),
m_profileElapsedMS(0), m_profileElapsedMS(0),
m_profilingVerbosity(0), m_profilingVerbosity(0),
settings(0), settings(0),
@@ -849,6 +870,11 @@ void PluginManagerPrivate::readSettings()
*/ */
void PluginManagerPrivate::stopAll() void PluginManagerPrivate::stopAll()
{ {
if (delayedInitializeTimer && delayedInitializeTimer->isActive()) {
delayedInitializeTimer->stop();
delete delayedInitializeTimer;
delayedInitializeTimer = 0;
}
QList<PluginSpec *> queue = loadQueue(); QList<PluginSpec *> queue = loadQueue();
foreach (PluginSpec *spec, queue) { foreach (PluginSpec *spec, queue) {
loadPlugin(spec, PluginSpec::Stopped); loadPlugin(spec, PluginSpec::Stopped);
@@ -941,9 +967,19 @@ void PluginManagerPrivate::loadPlugins()
QListIterator<PluginSpec *> it(queue); QListIterator<PluginSpec *> it(queue);
it.toBack(); it.toBack();
while (it.hasPrevious()) { 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(); emit q->pluginsChanged();
delayedInitializeTimer = new QTimer;
delayedInitializeTimer->setInterval(DELAYED_INITIALIZE_INTERVAL);
delayedInitializeTimer->setSingleShot(true);
connect(delayedInitializeTimer, SIGNAL(timeout()),
this, SLOT(nextDelayedInitialize()));
delayedInitializeTimer->start();
} }
/*! /*!

View File

@@ -42,6 +42,7 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QTime; class QTime;
class QTimer;
class QSettings; class QSettings;
class QEventLoop; class QEventLoop;
QT_END_NAMESPACE QT_END_NAMESPACE
@@ -90,6 +91,10 @@ public:
QStringList defaultDisabledPlugins; QStringList defaultDisabledPlugins;
QStringList disabledPlugins; QStringList disabledPlugins;
QStringList forceEnabledPlugins; QStringList forceEnabledPlugins;
// delayed initialization
QTimer *delayedInitializeTimer;
QList<PluginSpec *> delayedInitializeQueue;
// ansynchronous shutdown
QList<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown QList<PluginSpec *> asynchronousPlugins; // plugins that have requested async shutdown
QEventLoop *shutdownEventLoop; // used for async shutdown QEventLoop *shutdownEventLoop; // used for async shutdown
@@ -109,6 +114,7 @@ public:
static PluginSpecPrivate *privateSpec(PluginSpec *spec); static PluginSpecPrivate *privateSpec(PluginSpec *spec);
private slots: private slots:
void nextDelayedInitialize();
void asyncShutdownFinished(); void asyncShutdownFinished();
private: private:

View File

@@ -1013,6 +1013,25 @@ bool PluginSpecPrivate::initializeExtensions()
return true; 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() \fn bool PluginSpecPrivate::stop()
\internal \internal

View File

@@ -60,6 +60,7 @@ public:
bool loadLibrary(); bool loadLibrary();
bool initializePlugin(); bool initializePlugin();
bool initializeExtensions(); bool initializeExtensions();
bool delayedInitialize();
IPlugin::ShutdownFlag stop(); IPlugin::ShutdownFlag stop();
void kill(); void kill();

View File

@@ -31,13 +31,14 @@
**************************************************************************/ **************************************************************************/
#include "coreplugin.h" #include "coreplugin.h"
#include "designmode.h"
#include "editmode.h" #include "editmode.h"
#include "editormanager.h" #include "editormanager.h"
#include "mainwindow.h"
#include "modemanager.h"
#include "fileiconprovider.h" #include "fileiconprovider.h"
#include "designmode.h" #include "helpmanager.h"
#include "mainwindow.h"
#include "mimedatabase.h" #include "mimedatabase.h"
#include "modemanager.h"
#include <extensionsystem/pluginmanager.h> #include <extensionsystem/pluginmanager.h>
@@ -105,6 +106,12 @@ void CorePlugin::extensionsInitialized()
m_mainWindow->extensionsInitialized(); m_mainWindow->extensionsInitialized();
} }
bool CorePlugin::delayedInitialize()
{
HelpManager::instance()->setupHelpManager();
return true;
}
void CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args) void CorePlugin::remoteCommand(const QStringList & /* options */, const QStringList &args)
{ {
m_mainWindow->openFiles(args, ICore::SwitchMode); m_mainWindow->openFiles(args, ICore::SwitchMode);

View File

@@ -50,10 +50,11 @@ public:
CorePlugin(); CorePlugin();
~CorePlugin(); ~CorePlugin();
virtual bool initialize(const QStringList &arguments, QString *errorMessage = 0); bool initialize(const QStringList &arguments, QString *errorMessage = 0);
virtual void extensionsInitialized(); void extensionsInitialized();
virtual ShutdownFlag aboutToShutdown(); bool delayedInitialize();
virtual void remoteCommand(const QStringList & /* options */, const QStringList &args); ShutdownFlag aboutToShutdown();
void remoteCommand(const QStringList & /* options */, const QStringList &args);
public slots: public slots:
void fileOpenRequest(const QString&); void fileOpenRequest(const QString&);

View File

@@ -40,7 +40,6 @@
#include <QtCore/QDir> #include <QtCore/QDir>
#include <QtCore/QFileInfo> #include <QtCore/QFileInfo>
#include <QtCore/QStringList> #include <QtCore/QStringList>
#include <QtCore/QTimer>
#include <QtHelp/QHelpEngineCore> #include <QtHelp/QHelpEngineCore>
@@ -91,7 +90,6 @@ HelpManager::HelpManager(QObject *parent) :
{ {
Q_ASSERT(!m_instance); Q_ASSERT(!m_instance);
m_instance = this; m_instance = this;
connect(Core::ICore::instance(), SIGNAL(coreOpened()), SLOT(delayedSetupHelpManager()));
} }
HelpManager::~HelpManager() HelpManager::~HelpManager()
@@ -102,11 +100,6 @@ HelpManager::~HelpManager()
delete d; delete d;
} }
void HelpManager::delayedSetupHelpManager()
{
QTimer::singleShot(100, this, SLOT(setupHelpManager()));
}
HelpManager *HelpManager::instance() HelpManager *HelpManager::instance()
{ {
Q_ASSERT(m_instance); Q_ASSERT(m_instance);

View File

@@ -46,6 +46,10 @@ QT_FORWARD_DECLARE_CLASS(QUrl)
namespace Core { namespace Core {
struct HelpManagerPrivate; struct HelpManagerPrivate;
namespace Internal {
class CorePlugin;
}
class CORE_EXPORT HelpManager : public QObject class CORE_EXPORT HelpManager : public QObject
{ {
Q_OBJECT Q_OBJECT
@@ -91,13 +95,11 @@ signals:
void collectionFileChanged(); void collectionFileChanged();
void helpRequested(const QUrl &url); void helpRequested(const QUrl &url);
private slots:
void delayedSetupHelpManager();
void setupHelpManager();
private: private:
void setupHelpManager();
void verifyDocumenation(); void verifyDocumenation();
HelpManagerPrivate *d; HelpManagerPrivate *d;
friend class Internal::CorePlugin; // setupHelpManager
}; };
} // Core } // Core

View File

@@ -139,7 +139,6 @@ bool LocatorPlugin::initialize(const QStringList &, QString *)
addAutoReleasedObject(new LocatorFiltersFilter(this, m_locatorWidget)); addAutoReleasedObject(new LocatorFiltersFilter(this, m_locatorWidget));
connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(startSettingsLoad()));
return true; return true;
} }
@@ -167,10 +166,11 @@ void LocatorPlugin::extensionsInitialized()
setFilters(m_filters); setFilters(m_filters);
} }
void LocatorPlugin::startSettingsLoad() bool LocatorPlugin::delayedInitialize()
{ {
connect(&m_loadWatcher, SIGNAL(finished()), this, SLOT(settingsLoaded())); connect(&m_loadWatcher, SIGNAL(finished()), this, SLOT(settingsLoaded()));
m_loadWatcher.setFuture(QtConcurrent::run(this, &LocatorPlugin::loadSettings)); m_loadWatcher.setFuture(QtConcurrent::run(this, &LocatorPlugin::loadSettings));
return true;
} }
void LocatorPlugin::loadSettings() void LocatorPlugin::loadSettings()

View File

@@ -63,6 +63,7 @@ public:
bool initialize(const QStringList &arguments, QString *errorMessage); bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized(); void extensionsInitialized();
bool delayedInitialize();
QList<ILocatorFilter*> filters(); QList<ILocatorFilter*> filters();
QList<ILocatorFilter*> customFilters(); QList<ILocatorFilter*> customFilters();
@@ -77,7 +78,6 @@ public slots:
void openLocator(); void openLocator();
private slots: private slots:
void startSettingsLoad();
void settingsLoaded(); void settingsLoaded();
void updatePlaceholderText(Core::Command *command = 0); void updatePlaceholderText(Core::Command *command = 0);

View File

@@ -80,7 +80,11 @@ bool QtSupportPlugin::initialize(const QStringList &arguments, QString *errorMes
void QtSupportPlugin::extensionsInitialized() void QtSupportPlugin::extensionsInitialized()
{ {
QtVersionManager::instance()->extensionsInitialized(); QtVersionManager::instance()->extensionsInitialized();
}
bool QtSupportPlugin::delayedInitialize()
{
return QtVersionManager::instance()->delayedInitialize();
} }
Q_EXPORT_PLUGIN(QtSupportPlugin) Q_EXPORT_PLUGIN(QtSupportPlugin)

View File

@@ -49,6 +49,7 @@ class QtSupportPlugin : public ExtensionSystem::IPlugin
public: public:
bool initialize(const QStringList &arguments, QString *errorMessage); bool initialize(const QStringList &arguments, QString *errorMessage);
void extensionsInitialized(); void extensionsInitialized();
bool delayedInitialize();
private slots: private slots:
#ifdef WITH_TESTS #ifdef WITH_TESTS

View File

@@ -138,10 +138,15 @@ void QtVersionManager::extensionsInitialized()
findSystemQt(); findSystemQt();
} }
connect(Core::ICore::instance(), SIGNAL(coreOpened()), this, SLOT(delayedUpdateDocumentation()));
saveQtVersions(); saveQtVersions();
} }
bool QtVersionManager::delayedInitialize()
{
updateDocumentation();
return true;
}
QtVersionManager::~QtVersionManager() QtVersionManager::~QtVersionManager()
{ {
qDeleteAll(m_versions); qDeleteAll(m_versions);
@@ -513,11 +518,6 @@ void QtVersionManager::updateDumpFor(const Utils::FileName &qmakeCommand)
emit dumpUpdatedFor(qmakeCommand); emit dumpUpdatedFor(qmakeCommand);
} }
void QtVersionManager::delayedUpdateDocumentation()
{
QTimer::singleShot(100, this, SLOT(updateDocumentation()));
}
int QtVersionManager::getUniqueId() int QtVersionManager::getUniqueId()
{ {
return m_idcount++; return m_idcount++;

View File

@@ -62,6 +62,7 @@ public:
QtVersionManager(); QtVersionManager();
~QtVersionManager(); ~QtVersionManager();
void extensionsInitialized(); void extensionsInitialized();
bool delayedInitialize();
// This will *always* return at least one (Qt in Path), even if that is // This will *always* return at least one (Qt in Path), even if that is
// unconfigured. // unconfigured.
@@ -110,10 +111,6 @@ signals:
public slots: public slots:
void updateDumpFor(const Utils::FileName &qmakeCommand); void updateDumpFor(const Utils::FileName &qmakeCommand);
private slots:
void delayedUpdateDocumentation();
void updateDocumentation();
private: private:
// This function is really simplistic... // This function is really simplistic...
static bool equals(BaseQtVersion *a, BaseQtVersion *b); static bool equals(BaseQtVersion *a, BaseQtVersion *b);
@@ -130,6 +127,7 @@ private:
void findSystemQt(); void findSystemQt();
void updateFromInstaller(); void updateFromInstaller();
void saveQtVersions(); void saveQtVersions();
void updateDocumentation();
// Used by QtOptionsPage // Used by QtOptionsPage
void setNewQtVersions(QList<BaseQtVersion *> newVersions); void setNewQtVersions(QList<BaseQtVersion *> newVersions);
// Used by QtVersion // Used by QtVersion