Commit cc883023 authored by hjk's avatar hjk

De-emphasize PluginManager::getObjects<Type>()

... by additionally keeping local (currently non-owning) pools per
"interesting" type.

Current situation:
  - The global object pool does not scale well for looking up
    objects, as iteration plus qobject_cast typically iterates
    over all pooled objects.
  - User code that can use typed results from the object
    pool need to have access to the full type definition anyway,
    i.e.  depend on the plugin of the target class anyway.

The patch here solves the scaling problem is to have local
type-specific pools to which objects register in their
constructors and deregister in their destructors.

This patch here does *not* change the ownership model of the
pooled objects, however, it opens the possibility to change
the ownership model per type (e.g. by not putting things into
the global pool at all anymore and make the local pool 'owning')
and the intent is to handle that in later patchs.

Even without the follow-up patches this here is a performance
improvement for the cases that access the local pools instead
the global one, i.e. "practically all".

Change-Id: Ib11a42df2c4ecf5e1155534730083a520dd1995b
Reviewed-by: Eike Ziller's avatarEike Ziller <eike.ziller@qt.io>
Reviewed-by: Christian Kandeler's avatarChristian Kandeler <christian.kandeler@qt.io>
parent 32762e27
......@@ -82,6 +82,8 @@ public:
}
return results;
}
// This is useful for soft dependencies using pure interfaces.
template <typename T> static T *getObject()
{
QReadLocker lock(listLock());
......
......@@ -204,6 +204,24 @@ QString PropertyInfo::toString() const
return list.join('|');
}
static QList<CustomImportsProvider *> g_customImportProviders;
CustomImportsProvider::CustomImportsProvider(QObject *parent)
: QObject(parent)
{
g_customImportProviders.append(this);
}
CustomImportsProvider::~CustomImportsProvider()
{
g_customImportProviders.removeOne(this);
}
const QList<CustomImportsProvider *> CustomImportsProvider::allProviders()
{
return g_customImportProviders;
}
} // namespace QmlJS
CppComponentValue::CppComponentValue(FakeMetaObject::ConstPtr metaObject, const QString &className,
......
......@@ -1127,8 +1127,11 @@ class QMLJS_EXPORT CustomImportsProvider : public QObject
{
Q_OBJECT
public:
explicit CustomImportsProvider(QObject *parent = 0) : QObject(parent) {}
virtual ~CustomImportsProvider() {}
explicit CustomImportsProvider(QObject *parent = nullptr);
virtual ~CustomImportsProvider();
static const QList<CustomImportsProvider *> allProviders();
virtual QList<Import> imports(ValueOwner *valueOwner, const Document *context) const = 0;
};
......
......@@ -33,8 +33,6 @@
#include "qmljsqrcparser.h"
#include "qmljsconstants.h"
#include <extensionsystem/pluginmanager.h>
#include <QDir>
using namespace LanguageUtils;
......@@ -212,12 +210,9 @@ Context::ImportsPerDocument LinkPrivate::linkImports()
Imports *imports = new Imports(valueOwner);
// Add custom imports for the opened document
if (ExtensionSystem::PluginManager::instance()) {
auto providers = ExtensionSystem::PluginManager::getObjects<CustomImportsProvider>();
foreach (const auto &provider, providers)
foreach (const auto &import, provider->imports(valueOwner, document.data()))
importCache.insert(ImportCacheKey(import.info), import);
}
for (const auto &provider : CustomImportsProvider::allProviders())
foreach (const auto &import, provider->imports(valueOwner, document.data()))
importCache.insert(ImportCacheKey(import.info), import);
populateImportedTypes(imports, document);
importsPerDocument.insert(document.data(), QSharedPointer<Imports>(imports));
......
......@@ -41,8 +41,6 @@
#include <coreplugin/messagemanager.h>
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <projectexplorer/buildconfiguration.h>
#include <projectexplorer/project.h>
#include <projectexplorer/projectexplorer.h>
......@@ -92,6 +90,18 @@ static bool openXmlFile(QDomDocument &doc, const Utils::FileName &fileName);
static bool openManifest(ProjectExplorer::Target *target, QDomDocument &doc);
static int parseMinSdk(const QDomElement &manifestElem);
static QList<AndroidQtSupport *> g_androidQtSupportProviders;
AndroidQtSupport::AndroidQtSupport()
{
g_androidQtSupportProviders.append(this);
}
AndroidQtSupport::~AndroidQtSupport()
{
g_androidQtSupportProviders.removeOne(this);
}
bool AndroidManager::supportsAndroid(const ProjectExplorer::Kit *kit)
{
QtSupport::BaseQtVersion *version = QtSupport::QtKitInformation::qtVersion(kit);
......@@ -457,8 +467,7 @@ bool AndroidManager::checkForQt51Files(Utils::FileName fileName)
AndroidQtSupport *AndroidManager::androidQtSupport(ProjectExplorer::Target *target)
{
QList<AndroidQtSupport *> providerList = ExtensionSystem::PluginManager::getObjects<AndroidQtSupport>();
foreach (AndroidQtSupport *provider, providerList) {
for (AndroidQtSupport *provider : g_androidQtSupportProviders) {
if (provider->canHandle(target))
return provider;
}
......
......@@ -45,6 +45,10 @@ class ANDROID_EXPORT AndroidQtSupport : public QObject
{
Q_OBJECT
protected:
AndroidQtSupport();
~AndroidQtSupport();
public:
enum BuildType {
DebugBuild,
......@@ -52,7 +56,6 @@ public:
ReleaseBuildSigned
};
public:
virtual bool canHandle(const ProjectExplorer::Target *target) const = 0;
virtual QStringList soLibSearchPath(const ProjectExplorer::Target *target) const = 0;
virtual QStringList androidExtraLibs(const ProjectExplorer::Target *target) const = 0;
......
......@@ -28,14 +28,24 @@
#include "basefilewizardfactory.h"
#include "ifilewizardextension.h"
#include <extensionsystem/pluginmanager.h>
#include <QMessageBox>
using namespace Utils;
namespace Core {
static QList<IFileWizardExtension *> g_fileWizardExtensions;
IFileWizardExtension::IFileWizardExtension()
{
g_fileWizardExtensions.append(this);
}
IFileWizardExtension::~IFileWizardExtension()
{
g_fileWizardExtensions.removeOne(this);
}
BaseFileWizard::BaseFileWizard(const BaseFileWizardFactory *factory,
const QVariantMap &extraValues,
QWidget *parent) :
......@@ -43,19 +53,8 @@ BaseFileWizard::BaseFileWizard(const BaseFileWizardFactory *factory,
m_extraValues(extraValues),
m_factory(factory)
{
// Compile extension pages, purge out unused ones
QList<IFileWizardExtension *> extensionList
= ExtensionSystem::PluginManager::getObjects<IFileWizardExtension>();
for (auto it = extensionList.begin(); it != extensionList.end(); ) {
const QList<QWizardPage *> extensionPages = (*it)->extensionPages(factory);
if (extensionPages.empty()) {
it = extensionList.erase(it);
} else {
m_extensionPages += extensionPages;
++it;
}
}
for (IFileWizardExtension *extension : g_fileWizardExtensions)
m_extensionPages += extension->extensionPages(factory);
if (!m_extensionPages.empty())
m_firstExtensionPage = m_extensionPages.front();
......@@ -67,9 +66,7 @@ void BaseFileWizard::initializePage(int id)
if (page(id) == m_firstExtensionPage) {
generateFileList();
QList<IFileWizardExtension *> extensionList
= ExtensionSystem::PluginManager::getObjects<IFileWizardExtension>();
foreach (IFileWizardExtension *ex, extensionList)
for (IFileWizardExtension *ex : g_fileWizardExtensions)
ex->firstExtensionPageShown(m_files, m_extraValues);
}
}
......@@ -99,9 +96,7 @@ void BaseFileWizard::accept()
break;
}
QList<IFileWizardExtension *> extensionList
= ExtensionSystem::PluginManager::getObjects<IFileWizardExtension>();
foreach (IFileWizardExtension *ex, extensionList) {
for (IFileWizardExtension *ex : g_fileWizardExtensions) {
for (int i = 0; i < m_files.count(); i++) {
ex->applyCodeStyle(&m_files[i]);
}
......@@ -116,7 +111,7 @@ void BaseFileWizard::accept()
bool removeOpenProjectAttribute = false;
// Run the extensions
foreach (IFileWizardExtension *ex, extensionList) {
for (IFileWizardExtension *ex : g_fileWizardExtensions) {
bool remove;
if (!ex->processFiles(m_files, &remove, &errorMessage)) {
if (!errorMessage.isEmpty())
......
......@@ -135,6 +135,7 @@ QIcon Core::IOptionsPage::categoryIcon() const
Sets \a categoryIcon as the category icon of the options page.
*/
static QList<Core::IOptionsPage *> g_optionsPages;
/*!
Constructs an options page with the given \a parent.
......@@ -143,7 +144,7 @@ Core::IOptionsPage::IOptionsPage(QObject *parent)
: QObject(parent),
m_keywordsInitialized(false)
{
g_optionsPages.append(this);
}
/*!
......@@ -151,6 +152,12 @@ Core::IOptionsPage::IOptionsPage(QObject *parent)
*/
Core::IOptionsPage::~IOptionsPage()
{
g_optionsPages.removeOne(this);
}
const QList<Core::IOptionsPage *> Core::IOptionsPage::allOptionsPages()
{
return g_optionsPages;
}
/*!
......@@ -183,6 +190,24 @@ bool Core::IOptionsPage::matches(const QString &searchKeyWord) const
return false;
}
static QList<Core::IOptionsPageProvider *> g_optionsPagesProviders;
Core::IOptionsPageProvider::IOptionsPageProvider(QObject *parent)
: QObject(parent)
{
g_optionsPagesProviders.append(this);
}
Core::IOptionsPageProvider::~IOptionsPageProvider()
{
g_optionsPagesProviders.removeOne(this);
}
const QList<Core::IOptionsPageProvider *> Core::IOptionsPageProvider::allOptionsPagesProviders()
{
return g_optionsPagesProviders;
}
QIcon Core::IOptionsPageProvider::categoryIcon() const
{
return QIcon(m_categoryIcon);
......
......@@ -47,6 +47,8 @@ public:
IOptionsPage(QObject *parent = 0);
virtual ~IOptionsPage();
static const QList<IOptionsPage *> allOptionsPages();
Id id() const { return m_id; }
QString displayName() const { return m_displayName; }
Id category() const { return m_category; }
......@@ -88,7 +90,10 @@ class CORE_EXPORT IOptionsPageProvider : public QObject
Q_OBJECT
public:
IOptionsPageProvider(QObject *parent = 0) : QObject(parent) {}
IOptionsPageProvider(QObject *parent = nullptr);
~IOptionsPageProvider();
static const QList<IOptionsPageProvider *> allOptionsPagesProviders();
Id category() const { return m_category; }
QString displayCategory() const { return m_displayCategory; }
......
......@@ -27,7 +27,6 @@
#include <coreplugin/icore.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/algorithm.h>
#include <utils/hostosinfo.h>
#include <utils/fancylineedit.h>
......@@ -69,7 +68,7 @@ bool optionsPageLessThan(const IOptionsPage *p1, const IOptionsPage *p2)
static inline QList<IOptionsPage*> sortedOptionsPages()
{
QList<IOptionsPage*> rc = ExtensionSystem::PluginManager::getObjects<IOptionsPage>();
QList<IOptionsPage*> rc = IOptionsPage::allOptionsPages();
std::stable_sort(rc.begin(), rc.end(), optionsPageLessThan);
return rc;
}
......@@ -414,8 +413,7 @@ SettingsDialog::SettingsDialog(QWidget *parent) :
else
setWindowTitle(tr("Options"));
m_model->setPages(m_pages,
ExtensionSystem::PluginManager::getObjects<IOptionsPageProvider>());
m_model->setPages(m_pages, IOptionsPageProvider::allOptionsPagesProviders());
m_proxyModel->setSourceModel(m_model);
m_proxyModel->setFilterCaseSensitivity(Qt::CaseInsensitive);
......
......@@ -25,13 +25,23 @@
#include "diffservice.h"
#include <extensionsystem/pluginmanager.h>
namespace Core {
static DiffService *g_instance = nullptr;
DiffService::DiffService()
{
g_instance = this;
}
DiffService::~DiffService()
{
g_instance = nullptr;
}
DiffService *DiffService::instance()
{
return ExtensionSystem::PluginManager::getObject<DiffService>();
return g_instance;
}
} // Core
......@@ -38,7 +38,8 @@ class CORE_EXPORT DiffService
public:
static DiffService *instance();
virtual ~DiffService() {}
DiffService();
virtual ~DiffService();
virtual void diffFiles(const QString &leftFileName, const QString &rightFileName) = 0;
virtual void diffModifiedFiles(const QStringList &fileNames) = 0;
......
......@@ -711,24 +711,26 @@ bool DocumentManager::saveDocument(IDocument *document, const QString &fileName,
return ret;
}
template<typename FactoryType>
QSet<QString> filterStrings()
QString DocumentManager::allDocumentFactoryFiltersString(QString *allFilesFilter = 0)
{
QSet<QString> filters;
for (FactoryType *factory : ExtensionSystem::PluginManager::getObjects<FactoryType>()) {
QSet<QString> uniqueFilters;
for (IEditorFactory *factory : IEditorFactory::allEditorFactories()) {
for (const QString &mt : factory->mimeTypes()) {
const QString filter = mimeTypeForName(mt).filterString();
if (!filter.isEmpty())
filters.insert(filter);
uniqueFilters.insert(filter);
}
}
for (IDocumentFactory *factory : IDocumentFactory::allDocumentFactories()) {
for (const QString &mt : factory->mimeTypes()) {
const QString filter = mimeTypeForName(mt).filterString();
if (!filter.isEmpty())
uniqueFilters.insert(filter);
}
}
return filters;
}
QString DocumentManager::allDocumentFactoryFiltersString(QString *allFilesFilter = 0)
{
const QSet<QString> uniqueFilters = filterStrings<IDocumentFactory>()
+ filterStrings<IEditorFactory>();
QStringList filters = uniqueFilters.toList();
filters.sort();
const QString allFiles = Utils::allFilesFilterString();
......
......@@ -186,17 +186,6 @@ static void setFocusToEditorViewAndUnmaximizePanes(EditorView *view)
}
}
/* For something that has a 'QString id' (IEditorFactory
* or IExternalEditor), find the one matching a id. */
template <class EditorFactoryLike>
EditorFactoryLike *findById(Id id)
{
return ExtensionSystem::PluginManager::getObject<EditorFactoryLike>(
[&id](EditorFactoryLike *efl) {
return id == efl->id();
});
}
EditorManagerPrivate::EditorManagerPrivate(QObject *parent) :
QObject(parent),
m_revertToSavedAction(new QAction(EditorManager::tr("Revert to Saved"), this)),
......@@ -606,7 +595,9 @@ IEditor *EditorManagerPrivate::openEditor(EditorView *view, const QString &fileN
return 0;
}
if (editorId.isValid()) {
if (IEditorFactory *factory = findById<IEditorFactory>(editorId)) {
IEditorFactory *factory = Utils::findOrDefault(IEditorFactory::allEditorFactories(),
Utils::equal(&IEditorFactory::id, editorId));
if (factory) {
factories.removeOne(factory);
factories.push_front(factory);
}
......@@ -1139,7 +1130,9 @@ EditorManager::EditorFactoryList EditorManagerPrivate::findFactories(Id editorId
factories = EditorManager::editorFactories(mimeType, false);
} else {
// Find by editor id
if (IEditorFactory *factory = findById<IEditorFactory>(editorId))
IEditorFactory *factory = Utils::findOrDefault(IEditorFactory::allEditorFactories(),
Utils::equal(&IEditorFactory::id, editorId));
if (factory)
factories.push_back(factory);
}
if (factories.empty()) {
......@@ -2606,7 +2599,7 @@ EditorManager::EditorFactoryList
EditorManager::editorFactories(const Utils::MimeType &mimeType, bool bestMatchOnly)
{
EditorFactoryList rc;
const EditorFactoryList allFactories = ExtensionSystem::PluginManager::getObjects<IEditorFactory>();
const EditorFactoryList allFactories = IEditorFactory::allEditorFactories();
mimeTypeFactoryLookup(mimeType, allFactories, bestMatchOnly, &rc);
if (debugEditorManager)
qDebug() << Q_FUNC_INFO << mimeType.name() << " returns " << rc;
......@@ -2617,7 +2610,7 @@ EditorManager::ExternalEditorList
EditorManager::externalEditors(const Utils::MimeType &mimeType, bool bestMatchOnly)
{
ExternalEditorList rc;
const ExternalEditorList allEditors = ExtensionSystem::PluginManager::getObjects<IExternalEditor>();
const ExternalEditorList allEditors = IExternalEditor::allExternalEditors();
mimeTypeFactoryLookup(mimeType, allEditors, bestMatchOnly, &rc);
if (debugEditorManager)
qDebug() << Q_FUNC_INFO << mimeType.name() << " returns " << rc;
......@@ -2692,7 +2685,8 @@ bool EditorManager::isAutoSaveFile(const QString &fileName)
bool EditorManager::openExternalEditor(const QString &fileName, Id editorId)
{
IExternalEditor *ee = findById<IExternalEditor>(editorId);
IExternalEditor *ee = Utils::findOrDefault(IExternalEditor::allExternalEditors(),
Utils::equal(&IExternalEditor::id, editorId));
if (!ee)
return false;
QString errorMessage;
......
......@@ -27,9 +27,24 @@
#include <utils/qtcassert.h>
Core::IEditorFactory::IEditorFactory(QObject *parent)
namespace Core {
static QList<IEditorFactory *> g_editorFactories;
IEditorFactory::IEditorFactory(QObject *parent)
: QObject(parent)
{
g_editorFactories.append(this);
}
IEditorFactory::~IEditorFactory()
{
g_editorFactories.removeOne(this);
}
const QList<IEditorFactory *> IEditorFactory::allEditorFactories()
{
return g_editorFactories;
}
} // Core
......@@ -40,7 +40,11 @@ class CORE_EXPORT IEditorFactory : public QObject
Q_OBJECT
public:
IEditorFactory(QObject *parent = 0);
IEditorFactory(QObject *parent = nullptr);
~IEditorFactory();
static const QList<IEditorFactory *> allEditorFactories();
QString displayName() const { return m_displayName; }
void setDisplayName(const QString &displayName) { m_displayName = displayName; }
......
......@@ -25,6 +25,8 @@
#include "iexternaleditor.h"
namespace Core {
/*!
\class Core::IExternalEditor
\mainclass
......@@ -50,3 +52,23 @@
Opens the editor with \a fileName. Returns \c true on success or \c false
on failure along with the error in \a errorMessage.
*/
static QList<IExternalEditor *> g_externalEditors;
IExternalEditor::IExternalEditor(QObject *parent)
: QObject(parent)
{
g_externalEditors.append(this);
}
IExternalEditor::~IExternalEditor()
{
g_externalEditors.removeOne(this);
}
const QList<IExternalEditor *> IExternalEditor::allExternalEditors()
{
return g_externalEditors;
}
} // Core
......@@ -38,7 +38,10 @@ class CORE_EXPORT IExternalEditor : public QObject
Q_OBJECT
public:
explicit IExternalEditor(QObject *parent = 0) : QObject(parent) {}
explicit IExternalEditor(QObject *parent = nullptr);
~IExternalEditor();
static const QList<IExternalEditor *> allExternalEditors();
virtual QStringList mimeTypes() const = 0;
virtual Id id() const = 0;
......
......@@ -202,13 +202,12 @@ static QString filterActionName(const IFindFilter *filter)
void FindPrivate::setupFilterMenuItems()
{
QList<IFindFilter*> findInterfaces = ExtensionSystem::PluginManager::getObjects<IFindFilter>();
Command *cmd;
ActionContainer *mfindadvanced = ActionManager::actionContainer(Constants::M_FIND_ADVANCED);
bool haveEnabledFilters = false;
const Id base("FindFilter.");
QList<IFindFilter *> sortedFilters = findInterfaces;
QList<IFindFilter *> sortedFilters = IFindFilter::allFindFilters();
Utils::sort(sortedFilters, &IFindFilter::displayName);
foreach (IFindFilter *filter, sortedFilters) {
QAction *action = new QAction(filterActionName(filter), this);
......
......@@ -36,8 +36,6 @@
#include <coreplugin/actionmanager/command.h>
#include <coreplugin/findplaceholder.h>
#include <extensionsystem/pluginmanager.h>
#include <utils/hostosinfo.h>
#include <utils/qtcassert.h>
#include <utils/stylehelper.h>
......@@ -727,10 +725,10 @@ void FindToolBar::hideAndResetFocus()
FindToolBarPlaceHolder *FindToolBar::findToolBarPlaceHolder() const
{
QList<FindToolBarPlaceHolder*> placeholders = ExtensionSystem::PluginManager::getObjects<FindToolBarPlaceHolder>();
const QList<FindToolBarPlaceHolder*> placeholders = FindToolBarPlaceHolder::allFindToolbarPlaceHolders();
QWidget *candidate = QApplication::focusWidget();
while (candidate) {
foreach (FindToolBarPlaceHolder *ph, placeholders) {
for (FindToolBarPlaceHolder *ph : placeholders) {
if (ph->owner() == candidate)
return ph;
}
......
......@@ -227,6 +227,23 @@
namespace Core {
static QList<IFindFilter *> g_findFilters;
IFindFilter::IFindFilter()
{
g_findFilters.append(this);
}
IFindFilter::~IFindFilter()
{
g_findFilters.removeOne(this);
}
const QList<IFindFilter *> IFindFilter::allFindFilters()
{
return g_findFilters;
}
QKeySequence IFindFilter::defaultShortcut() const
{
return QKeySequence();
......
......@@ -39,9 +39,12 @@ namespace Core {
class CORE_EXPORT IFindFilter : public QObject
{
Q_OBJECT
public:
IFindFilter();
virtual ~IFindFilter();
virtual ~IFindFilter() {}
static const QList<IFindFilter *> allFindFilters();
virtual QString id() const = 0;
virtual QString displayName() const = 0;
......
......@@ -26,26 +26,26 @@
#include "findplaceholder.h"
#include "find/findtoolbar.h"
#include <extensionsystem/pluginmanager.h>
#include <QVBoxLayout>
using namespace Core;
FindToolBarPlaceHolder *FindToolBarPlaceHolder::m_current = 0;
static QList<FindToolBarPlaceHolder *> g_findToolBarPlaceHolders;
FindToolBarPlaceHolder::FindToolBarPlaceHolder(QWidget *owner, QWidget *parent)
: QWidget(parent), m_owner(owner), m_subWidget(0), m_lightColored(false)
{
g_findToolBarPlaceHolders.append(this);
setLayout(new QVBoxLayout);
setSizePolicy(QSizePolicy::Preferred, QSizePolicy::Maximum);
layout()->setMargin(0);
ExtensionSystem::PluginManager::addObject(this);
}
FindToolBarPlaceHolder::~FindToolBarPlaceHolder()
{
ExtensionSystem::PluginManager::removeObject(this);
g_findToolBarPlaceHolders.removeOne(this);
if (m_subWidget) {
m_subWidget->setVisible(false);
m_subWidget->setParent(0);
......@@ -54,6 +54,11 @@ FindToolBarPlaceHolder::~FindToolBarPlaceHolder()
m_current = 0;
}
const QList<FindToolBarPlaceHolder *> FindToolBarPlaceHolder::allFindToolbarPlaceHolders()
{
return g_findToolBarPlaceHolders;
}
QWidget *FindToolBarPlaceHolder::owner() const
{
return m_owner;
......
......@@ -39,6 +39,9 @@ class CORE_EXPORT FindToolBarPlaceHolder : public QWidget
public:
explicit FindToolBarPlaceHolder(QWidget *owner, QWidget *parent = 0);
~FindToolBarPlaceHolder();
static const QList<FindToolBarPlaceHolder *> allFindToolbarPlaceHolders();
QWidget *owner() const;
bool isUsedByWidget(QWidget *widget);
......