Commit de290e03 authored by Eike Ziller's avatar Eike Ziller

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: default avatarTobias Hunger <tobias.hunger@nokia.com>
parent 8a25c535
......@@ -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()
*/
/*!
......
......@@ -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 */) { }
......
......@@ -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();
}
/*!
......
......@@ -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:
......
......@@ -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
......
......@@ -60,6 +60,7 @@ public:
bool loadLibrary();
bool initializePlugin();
bool initializeExtensions();
bool delayedInitialize();
IPlugin::ShutdownFlag stop();
void kill();
......
......@@ -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);
......
......@@ -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&);
......
......@@ -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);
......
......@@ -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
......
......@@ -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()
......
......@@ -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);
......
......@@ -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)
......@@ -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
......
......@@ -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++;
......
......@@ -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
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment