diff --git a/src/libs/extensionsystem/iplugin.cpp b/src/libs/extensionsystem/iplugin.cpp index 9f7ca221e51..6661a46f610 100644 --- a/src/libs/extensionsystem/iplugin.cpp +++ b/src/libs/extensionsystem/iplugin.cpp @@ -161,12 +161,47 @@ namespace ExtensionSystem { namespace Internal { +class ObjectInitializer +{ +public: + ObjectCreator creator; + ObjectDestructor destructor; + ObjectCreationPolicy policy; +}; + class IPluginPrivate { public: + void tryCreateObjects(); + QList testCreators; + + QList objectInitializers; + QList> objectDestructors; + + // For debugging purposes: + QList createdObjects; // Not owned. }; +void IPluginPrivate::tryCreateObjects() +{ + QList unhandledObjectInitializers; + + for (const ObjectInitializer &initializer : std::as_const(objectInitializers)) { + if (!initializer.policy.dependsOn.isEmpty()) { + qWarning("Initialization dependencies are not supported yet"); + unhandledObjectInitializers.append(initializer); + continue; + } + + void *object = initializer.creator(); + createdObjects.append(object); + objectDestructors.append([initializer, object] { initializer.destructor(object); }); + } + + objectInitializers = unhandledObjectInitializers; +} + } // Internal /*! @@ -182,10 +217,20 @@ IPlugin::IPlugin() */ IPlugin::~IPlugin() { + for (const std::function &dtor : std::as_const(d->objectDestructors)) + dtor(); + delete d; d = nullptr; } +void IPlugin::addManagedHelper(const ObjectCreator &creator, + const ObjectDestructor &destructor, + const ObjectCreationPolicy &policy) +{ + d->objectInitializers.append({creator, destructor, policy}); +} + bool IPlugin::initialize(const QStringList &arguments, QString *errorString) { Q_UNUSED(arguments) @@ -194,6 +239,14 @@ bool IPlugin::initialize(const QStringList &arguments, QString *errorString) return true; } +/*! + \internal +*/ +void IPlugin::tryCreateObjects() +{ + d->tryCreateObjects(); +} + /*! Registers a function object that creates a test object. diff --git a/src/libs/extensionsystem/iplugin.h b/src/libs/extensionsystem/iplugin.h index 5a8fceb3d6e..3e477e42e81 100644 --- a/src/libs/extensionsystem/iplugin.h +++ b/src/libs/extensionsystem/iplugin.h @@ -5,6 +5,8 @@ #include "extensionsystem_global.h" +#include + #include #include @@ -15,6 +17,17 @@ namespace Internal { class IPluginPrivate; } using TestCreator = std::function; +using ObjectCreator = std::function; +using ObjectDestructor = std::function; + +struct EXTENSIONSYSTEM_EXPORT ObjectCreationPolicy +{ + // Can be empty if nothing depends on it. + Utils::Id id; + // Objects with empty dependencies are created as soon as possible. + QList dependsOn; +}; + class EXTENSIONSYSTEM_EXPORT IPlugin : public QObject { Q_OBJECT @@ -39,6 +52,7 @@ public: // Deprecated in 10.0, use addTest() virtual QVector createTestObjects() const; + virtual void tryCreateObjects(); protected: virtual void initialize() {} @@ -47,6 +61,17 @@ protected: void addTest(Args && ...args) { addTestCreator([args...] { return new Test(args...); }); } void addTestCreator(const TestCreator &creator); + template + void addManaged(const ObjectCreationPolicy &policy = {}) { + addManagedHelper([]() -> void * { return new Type(); }, + [](void *p) { delete static_cast(p); }, + policy); + } + + void addManagedHelper(const ObjectCreator &creator, + const ObjectDestructor &destructor, + const ObjectCreationPolicy &policy); + signals: void asynchronousShutdownFinished(); diff --git a/src/libs/extensionsystem/pluginspec.cpp b/src/libs/extensionsystem/pluginspec.cpp index d18f410e818..62b3c0096f6 100644 --- a/src/libs/extensionsystem/pluginspec.cpp +++ b/src/libs/extensionsystem/pluginspec.cpp @@ -1119,6 +1119,7 @@ bool PluginSpecPrivate::initializePlugin() hasError = true; return false; } + plugin->tryCreateObjects(); state = PluginSpec::Initialized; return true; } @@ -1145,6 +1146,7 @@ bool PluginSpecPrivate::initializeExtensions() return false; } plugin->extensionsInitialized(); + plugin->tryCreateObjects(); state = PluginSpec::Running; return true; } @@ -1164,7 +1166,9 @@ bool PluginSpecPrivate::delayedInitialize() hasError = true; return false; } - return plugin->delayedInitialize(); + const bool res = plugin->delayedInitialize(); + plugin->tryCreateObjects(); + return res; } /*!