forked from qt-creator/qt-creator
Delay modifications to MIME database until first use
Initialization of the MIME database takes time, and it is good to avoid this during startup. We nevertheless want to apply some modifications to the MIME database, so we need to delay these modifications until first use. Allow registration of additional initialization functions. Since the initialization functions access the MIME database, which does locking for thread- safety, we need to separate the initialization to outside these locking functions. Change-Id: I2b1706347768bcf081644e078ccfa45302d61641 Reviewed-by: <github-actions-qt-creator@cristianadam.eu> Reviewed-by: hjk <hjk@qt.io>
This commit is contained in:
@@ -957,6 +957,7 @@ void PluginManagerPrivate::nextDelayedInitialize()
|
||||
break; // do next delayedInitialize after a delay
|
||||
}
|
||||
if (delayedInitializeQueue.empty()) {
|
||||
Utils::setMimeStartupPhase(MimeStartupPhase::UpAndRunning);
|
||||
m_isInitializationDone = true;
|
||||
delete delayedInitializeTimer;
|
||||
delayedInitializeTimer = nullptr;
|
||||
@@ -1370,7 +1371,6 @@ void PluginManagerPrivate::loadPlugins()
|
||||
loadPlugin(spec, PluginSpec::Initialized);
|
||||
}
|
||||
|
||||
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
|
||||
{
|
||||
NANOTRACE_SCOPE("ExtensionSystem", "ExtensionsInitialized");
|
||||
Utils::reverseForeach(queue, [this](PluginSpec *spec) {
|
||||
@@ -1384,8 +1384,8 @@ void PluginManagerPrivate::loadPlugins()
|
||||
});
|
||||
}
|
||||
emit q->pluginsChanged();
|
||||
Utils::setMimeStartupPhase(MimeStartupPhase::UpAndRunning);
|
||||
|
||||
Utils::setMimeStartupPhase(MimeStartupPhase::PluginsDelayedInitializing);
|
||||
delayedInitializeTimer = new QTimer;
|
||||
delayedInitializeTimer->setInterval(DELAYED_INITIALIZE_INTERVAL);
|
||||
delayedInitializeTimer->setSingleShot(true);
|
||||
|
@@ -562,12 +562,9 @@ MimeDatabase::~MimeDatabase()
|
||||
*/
|
||||
MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const
|
||||
{
|
||||
d->checkInitPhase(nameOrAlias);
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
||||
qPrintable(nameOrAlias));
|
||||
|
||||
return d->mimeTypeForName(nameOrAlias);
|
||||
}
|
||||
|
||||
@@ -601,12 +598,9 @@ MimeType MimeDatabase::mimeTypeForName(const QString &nameOrAlias) const
|
||||
*/
|
||||
MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode) const
|
||||
{
|
||||
d->checkInitPhase(fileInfo.filePath());
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
||||
qPrintable(fileInfo.filePath()));
|
||||
|
||||
if (fileInfo.isDir())
|
||||
return d->mimeTypeForName(QLatin1String("inode/directory"));
|
||||
|
||||
@@ -659,12 +653,9 @@ MimeType MimeDatabase::mimeTypeForFile(const QFileInfo &fileInfo, MatchMode mode
|
||||
MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode) const
|
||||
{
|
||||
if (mode == MatchExtension) {
|
||||
d->checkInitPhase(fileName);
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
||||
qPrintable(fileName));
|
||||
|
||||
const QStringList matches = d->mimeTypeForFileName(fileName);
|
||||
const int matchCount = matches.count();
|
||||
if (matchCount == 0) {
|
||||
@@ -696,12 +687,9 @@ MimeType MimeDatabase::mimeTypeForFile(const QString &fileName, MatchMode mode)
|
||||
*/
|
||||
QList<MimeType> MimeDatabase::mimeTypesForFileName(const QString &fileName) const
|
||||
{
|
||||
d->checkInitPhase(fileName);
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized",
|
||||
qPrintable(fileName));
|
||||
|
||||
const QStringList matches = d->mimeTypeForFileName(fileName);
|
||||
QList<MimeType> mimes;
|
||||
mimes.reserve(matches.count());
|
||||
@@ -731,11 +719,9 @@ QString MimeDatabase::suffixForFileName(const QString &fileName) const
|
||||
*/
|
||||
MimeType MimeDatabase::mimeTypeForData(const QByteArray &data) const
|
||||
{
|
||||
d->checkInitPhase("data");
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
||||
qWarning("Accessing MimeDatabase for data before plugins are initialized");
|
||||
|
||||
int accuracy = 0;
|
||||
return d->findByData(data, &accuracy);
|
||||
}
|
||||
@@ -863,11 +849,9 @@ MimeType MimeDatabase::mimeTypeForFileNameAndData(const QString &fileName, const
|
||||
*/
|
||||
QList<MimeType> MimeDatabase::allMimeTypes() const
|
||||
{
|
||||
d->checkInitPhase("all mime types");
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase <= int(MimeStartupPhase::PluginsInitializing))
|
||||
qWarning("Accessing MimeDatabase for all mime types before plugins are initialized");
|
||||
|
||||
return d->allMimeTypes();
|
||||
}
|
||||
|
||||
@@ -924,4 +908,27 @@ void MimeDatabasePrivate::setGlobPatternsForMimeType(const MimeType &mimeType,
|
||||
}
|
||||
}
|
||||
|
||||
void MimeDatabasePrivate::checkInitPhase(const QString &info)
|
||||
{
|
||||
QReadLocker locker(&m_initMutex);
|
||||
if (m_startupPhase <= int(MimeStartupPhase::PluginsInitializing)) {
|
||||
qWarning("Accessing MimeDatabase for %s before plugins are initialized", qPrintable(info));
|
||||
return;
|
||||
}
|
||||
// run initialization functions and ensure providers are loaded
|
||||
// the initializers will call other MIME database functions which "checkInitPhase" again,
|
||||
// so make sure not to recurse
|
||||
if (!m_initialized.exchange(true)) {
|
||||
for (const std::function<void()> &f : m_initializers)
|
||||
f();
|
||||
QMutexLocker locker(&mutex);
|
||||
providers();
|
||||
}
|
||||
}
|
||||
|
||||
void MimeDatabasePrivate::addInitializer(const std::function<void()> &init)
|
||||
{
|
||||
m_initializers.append(init);
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
|
@@ -25,8 +25,11 @@
|
||||
#include <QtCore/qlist.h>
|
||||
#include <QtCore/qmutex.h>
|
||||
|
||||
#include <vector>
|
||||
#include <QReadWriteLock>
|
||||
|
||||
#include <atomic>
|
||||
#include <memory>
|
||||
#include <vector>
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
class QIODevice;
|
||||
@@ -75,6 +78,8 @@ public:
|
||||
void setMagicRulesForMimeType(const MimeType &mimeType,
|
||||
const QMap<int, QList<MimeMagicRule>> &rules);
|
||||
void setGlobPatternsForMimeType(const MimeType &mimeType, const QStringList &patterns);
|
||||
void checkInitPhase(const QString &info);
|
||||
void addInitializer(const std::function<void()> &init);
|
||||
|
||||
private:
|
||||
using Providers = std::vector<std::unique_ptr<MimeProviderBase>>;
|
||||
@@ -86,6 +91,7 @@ private:
|
||||
QElapsedTimer m_lastCheck;
|
||||
|
||||
// added for Qt Creator
|
||||
QList<std::function<void()>> m_initializers;
|
||||
QHash<QString, QByteArray> m_additionalData; // id -> data
|
||||
bool m_forceLoad = true;
|
||||
|
||||
@@ -94,6 +100,8 @@ public:
|
||||
QMutex mutex;
|
||||
|
||||
// added for Qt Creator
|
||||
QReadWriteLock m_initMutex;
|
||||
std::atomic_bool m_initialized = false;
|
||||
int m_startupPhase = 0;
|
||||
};
|
||||
|
||||
|
@@ -57,7 +57,7 @@ QList<MimeType> allMimeTypes()
|
||||
void setMimeStartupPhase(MimeStartupPhase phase)
|
||||
{
|
||||
auto d = MimeDatabasePrivate::instance();
|
||||
QMutexLocker locker(&d->mutex);
|
||||
QWriteLocker locker(&d->m_initMutex);
|
||||
if (int(phase) != d->m_startupPhase + 1) {
|
||||
qWarning("Unexpected jump in MimedDatabase lifetime from %d to %d",
|
||||
d->m_startupPhase,
|
||||
@@ -69,12 +69,14 @@ void setMimeStartupPhase(MimeStartupPhase phase)
|
||||
void addMimeTypes(const QString &id, const QByteArray &data)
|
||||
{
|
||||
auto d = MimeDatabasePrivate::instance();
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
if (d->m_startupPhase >= int(MimeStartupPhase::PluginsDelayedInitializing)) {
|
||||
qWarning("Adding items for ID \"%s\" to MimeDatabase after initialization time",
|
||||
qPrintable(id));
|
||||
{
|
||||
QReadLocker locker(&d->m_initMutex);
|
||||
if (d->m_startupPhase >= int(MimeStartupPhase::PluginsDelayedInitializing)) {
|
||||
qWarning("Adding items for ID \"%s\" to MimeDatabase after initialization time",
|
||||
qPrintable(id));
|
||||
}
|
||||
}
|
||||
QMutexLocker locker(&d->mutex);
|
||||
|
||||
d->addMimeData(id, data);
|
||||
}
|
||||
@@ -130,4 +132,14 @@ void visitMimeParents(const MimeType &mimeType,
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
The \a init function will be executed once after the MIME database is first initialized.
|
||||
It must be thread safe.
|
||||
*/
|
||||
void addMimeInitializer(const std::function<void()> &init)
|
||||
{
|
||||
auto d = MimeDatabasePrivate::instance();
|
||||
d->addInitializer(init);
|
||||
}
|
||||
|
||||
} // namespace Utils
|
||||
|
@@ -43,6 +43,7 @@ enum class MimeStartupPhase {
|
||||
};
|
||||
|
||||
QTCREATOR_UTILS_EXPORT void setMimeStartupPhase(MimeStartupPhase);
|
||||
QTCREATOR_UTILS_EXPORT void addMimeInitializer(const std::function<void()> &init);
|
||||
QTCREATOR_UTILS_EXPORT void addMimeTypes(const QString &id, const QByteArray &data);
|
||||
QTCREATOR_UTILS_EXPORT QMap<int, QList<MimeMagicRule>> magicRulesForMimeType(
|
||||
const MimeType &mimeType); // priority -> rules
|
||||
|
@@ -746,19 +746,25 @@ MimeTypeSettingsPrivate::UserMimeTypeHash MimeTypeSettingsPrivate::readUserModif
|
||||
return userMimeTypes;
|
||||
}
|
||||
|
||||
void MimeTypeSettingsPrivate::applyUserModifiedMimeTypes(const UserMimeTypeHash &mimeTypes)
|
||||
static void registerUserModifiedMimeTypes(const MimeTypeSettingsPrivate::UserMimeTypeHash &mimeTypes)
|
||||
{
|
||||
// register in mime data base, and remember for later
|
||||
for (auto it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it) {
|
||||
Utils::MimeType mt = Utils::mimeTypeForName(it.key());
|
||||
if (!mt.isValid()) // loaded from settings
|
||||
if (!mt.isValid())
|
||||
continue;
|
||||
m_userModifiedMimeTypes.insert(it.key(), it.value());
|
||||
Utils::setGlobPatternsForMimeType(mt, it.value().globPatterns);
|
||||
Utils::setMagicRulesForMimeType(mt, it.value().rules);
|
||||
}
|
||||
}
|
||||
|
||||
void MimeTypeSettingsPrivate::applyUserModifiedMimeTypes(const UserMimeTypeHash &mimeTypes)
|
||||
{
|
||||
// register in mime data base, and remember for later
|
||||
for (auto it = mimeTypes.constBegin(); it != mimeTypes.constEnd(); ++it)
|
||||
m_userModifiedMimeTypes.insert(it.key(), it.value());
|
||||
registerUserModifiedMimeTypes(mimeTypes);
|
||||
}
|
||||
|
||||
// MimeTypeSettingsPage
|
||||
|
||||
MimeTypeSettings::MimeTypeSettings()
|
||||
@@ -792,8 +798,9 @@ QStringList MimeTypeSettings::keywords() const
|
||||
void MimeTypeSettings::restoreSettings()
|
||||
{
|
||||
MimeTypeSettingsPrivate::UserMimeTypeHash mimetypes
|
||||
= MimeTypeSettingsPrivate::readUserModifiedMimeTypes();
|
||||
MimeTypeSettingsPrivate::applyUserModifiedMimeTypes(mimetypes);
|
||||
= MimeTypeSettingsPrivate::readUserModifiedMimeTypes();
|
||||
MimeTypeSettingsPrivate::m_userModifiedMimeTypes = mimetypes;
|
||||
Utils::addMimeInitializer([mimetypes] { registerUserModifiedMimeTypes(mimetypes); });
|
||||
}
|
||||
|
||||
QWidget *MimeEditorDelegate::createEditor(QWidget *parent,
|
||||
|
@@ -516,9 +516,7 @@ void CppEditorPlugin::initialize()
|
||||
void CppEditorPlugin::extensionsInitialized()
|
||||
{
|
||||
d->m_fileSettings.fromSettings(ICore::settings());
|
||||
if (!d->m_fileSettings.applySuffixesToMimeDB())
|
||||
qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
|
||||
|
||||
d->m_fileSettings.addMimeInitializer();
|
||||
const auto fileNamesPanelFactory = new ProjectPanelFactory;
|
||||
fileNamesPanelFactory->setPriority(99);
|
||||
fileNamesPanelFactory->setDisplayName(Tr::tr("C++ File Naming"));
|
||||
|
@@ -93,7 +93,7 @@ void CppFileSettings::fromSettings(QSettings *s)
|
||||
s->endGroup();
|
||||
}
|
||||
|
||||
bool CppFileSettings::applySuffixesToMimeDB()
|
||||
static bool applySuffixes(const QString &sourceSuffix, const QString &headerSuffix)
|
||||
{
|
||||
Utils::MimeType mt;
|
||||
mt = Utils::mimeTypeForName(QLatin1String(Constants::CPP_SOURCE_MIMETYPE));
|
||||
@@ -107,6 +107,19 @@ bool CppFileSettings::applySuffixesToMimeDB()
|
||||
return true;
|
||||
}
|
||||
|
||||
void CppFileSettings::addMimeInitializer() const
|
||||
{
|
||||
Utils::addMimeInitializer([sourceSuffix = sourceSuffix, headerSuffix = headerSuffix] {
|
||||
if (!applySuffixes(sourceSuffix, headerSuffix))
|
||||
qWarning("Unable to apply cpp suffixes to mime database (cpp mime types not found).\n");
|
||||
});
|
||||
}
|
||||
|
||||
bool CppFileSettings::applySuffixesToMimeDB()
|
||||
{
|
||||
return applySuffixes(sourceSuffix, headerSuffix);
|
||||
}
|
||||
|
||||
bool CppFileSettings::equals(const CppFileSettings &rhs) const
|
||||
{
|
||||
return lowerCaseFiles == rhs.lowerCaseFiles
|
||||
|
@@ -38,6 +38,7 @@ public:
|
||||
|
||||
void toSettings(QSettings *) const;
|
||||
void fromSettings(QSettings *);
|
||||
void addMimeInitializer() const;
|
||||
bool applySuffixesToMimeDB();
|
||||
|
||||
// Convenience to return a license template completely formatted.
|
||||
|
Reference in New Issue
Block a user