Commit 7d3d9cad authored by Friedemann Kleint's avatar Friedemann Kleint
Browse files

Fix code model indexing crash on Mac.

Introduce multithread-locking to Core::MimeDatabase as it is
invoked from the indexer thread to sort apart headers and sources.
Add a convenience to operate on a sequence to avoid locking for each
file.
parent 07bdbe04
......@@ -44,6 +44,7 @@
#include <QtCore/QSharedPointer>
#include <QtCore/QStringList>
#include <QtCore/QTextStream>
#include <QtCore/QMutexLocker>
#include <QtXml/QXmlStreamReader>
......@@ -1125,56 +1126,85 @@ MimeDatabase::~MimeDatabase()
MimeType MimeDatabase::findByType(const QString &typeOrAlias) const
{
return m_d->findByType(typeOrAlias);
m_mutex.lock();
const MimeType rc = m_d->findByType(typeOrAlias);
m_mutex.unlock();
return rc;
}
MimeType MimeDatabase::findByFile(const QFileInfo &f) const
MimeType MimeDatabase::findByFileUnlocked(const QFileInfo &f) const
{
return m_d->findByFile(f);
}
MimeType MimeDatabase::findByFile(const QFileInfo &f) const
{
m_mutex.lock();
const MimeType rc = findByFileUnlocked(f);
m_mutex.unlock();
return rc;
}
bool MimeDatabase::addMimeType(const MimeType &mt)
{
return m_d->addMimeType(mt);
m_mutex.lock();
const bool rc = m_d->addMimeType(mt);
m_mutex.unlock();
return rc;
}
bool MimeDatabase::addMimeTypes(const QString &fileName, QString *errorMessage)
{
return m_d->addMimeTypes(fileName, errorMessage);
m_mutex.lock();
const bool rc = m_d->addMimeTypes(fileName, errorMessage);
m_mutex.unlock();
return rc;
}
bool MimeDatabase::addMimeTypes(QIODevice *device, QString *errorMessage)
{
return m_d->addMimeTypes(device, errorMessage);
m_mutex.lock();
const bool rc = m_d->addMimeTypes(device, errorMessage);
m_mutex.unlock();
return rc;
}
QStringList MimeDatabase::suffixes() const
{
return m_d->suffixes();
m_mutex.lock();
const QStringList rc = m_d->suffixes();
m_mutex.unlock();
return rc;
}
QStringList MimeDatabase::filterStrings() const
{
return m_d->filterStrings();
m_mutex.lock();
const QStringList rc = m_d->filterStrings();
m_mutex.unlock();
return rc;
}
QString MimeDatabase::preferredSuffixByType(const QString &type) const
{
if (const MimeType mt = findByType(type))
return mt.preferredSuffix();
return mt.preferredSuffix(); // already does Mutex locking
return QString();
}
QString MimeDatabase::preferredSuffixByFile(const QFileInfo &f) const
{
if (const MimeType mt = findByFile(f))
return mt.preferredSuffix();
return mt.preferredSuffix(); // already does Mutex locking
return QString();
}
bool MimeDatabase::setPreferredSuffix(const QString &typeOrAlias, const QString &suffix)
{
return m_d->setPreferredSuffix(typeOrAlias, suffix);
m_mutex.lock();
const bool rc = m_d->setPreferredSuffix(typeOrAlias, suffix);
m_mutex.unlock();
return rc;
}
QDebug operator<<(QDebug d, const MimeDatabase &mt)
......
......@@ -35,6 +35,7 @@
#include <QtCore/QSharedDataPointer>
#include <QtCore/QSharedPointer>
#include <QtCore/QByteArray>
#include <QtCore/QMutex>
QT_BEGIN_NAMESPACE
class QIODevice;
......@@ -186,7 +187,7 @@ private:
/* A Mime data base to which the plugins can add the mime types they handle.
* When adding a "text/plain" to it, the mimetype will receive a magic matcher
* that checks for text files that do not match the globs by heuristics.
*
* The class is protected by a QMutex and can therefore be accessed by threads.
* A good testcase is to run it over '/usr/share/mime/<*>/<*>.xml' on Linux. */
class CORE_EXPORT MimeDatabase
......@@ -203,8 +204,15 @@ public:
// Returns a mime type or Null one if none found
MimeType findByType(const QString &type) const;
// Returns a mime type or Null one if none found
MimeType findByFile(const QFileInfo &f) const;
// Convenience that mutex-locks the DB and calls a function
// of the signature 'void f(const MimeType &, const QFileInfo &, const QString &)'
// for each filename of a sequence. This avoids locking the DB for each
// single file.
template <class Iterator, typename Function>
inline void findByFile(Iterator i1, const Iterator &i2, Function f) const;
// Convenience
QString preferredSuffixByType(const QString &type) const;
......@@ -219,9 +227,23 @@ public:
friend QDebug operator<<(QDebug d, const MimeDatabase &mt);
private:
MimeType findByFileUnlocked(const QFileInfo &f) const;
MimeDatabasePrivate *m_d;
mutable QMutex m_mutex;
};
template <class Iterator, typename Function>
void MimeDatabase::findByFile(Iterator i1, const Iterator &i2, Function f) const
{
m_mutex.lock();
for ( ; i1 != i2; ++i1) {
const QFileInfo fi(*i1);
f(findByFileUnlocked(fi), fi, *i1);
}
m_mutex.unlock();
}
} // namespace Core
#endif // MIMEDATABASE_H
......@@ -1227,6 +1227,41 @@ void CppModelManager::updateIncludesInPaths(QFutureInterface<void> &future,
future.reportFinished();
}
// Function that sorts headers and sources apart to be used for
// MimeDB::findByFile() on a sequence of file names.
class HeaderSourceSorter {
public:
explicit HeaderSourceSorter(QStringList *sources, QStringList *headers);
void operator()(const Core::MimeType &, const QFileInfo &, const QString &);
private:
QStringList m_sourceMimeTypes;
QStringList m_headerMimeTypes;
QStringList *m_sources;
QStringList *m_headers;
};
HeaderSourceSorter::HeaderSourceSorter(QStringList *sources, QStringList *headers) :
m_sources(sources),
m_headers(headers)
{
m_headerMimeTypes << QLatin1String("text/x-hdr") << QLatin1String("text/x-c++hdr");
m_sourceMimeTypes << QLatin1String("text/x-csrc") << QLatin1String("text/x-c++src")
<< QLatin1String("text/x-objcsrc");
}
void HeaderSourceSorter::operator()(const Core::MimeType &mimeType, const QFileInfo &, const QString &name)
{
if (mimeType) {
if (m_sourceMimeTypes.contains(mimeType.type())) {
m_sources->append(name);
} else if (m_headerMimeTypes.contains(mimeType.type())) {
m_headers->append(name);
}
}
}
void CppModelManager::parse(QFutureInterface<void> &future,
CppPreprocessor *preproc,
QStringList files)
......@@ -1234,31 +1269,17 @@ void CppModelManager::parse(QFutureInterface<void> &future,
if (files.isEmpty())
return;
Core::MimeDatabase *db = Core::ICore::instance()->mimeDatabase();
QStringList headers, sources;
Core::MimeType cSourceTy = db->findByType(QLatin1String("text/x-csrc"));
Core::MimeType cppSourceTy = db->findByType(QLatin1String("text/x-c++src"));
Core::MimeType mSourceTy = db->findByType(QLatin1String("text/x-objcsrc"));
Core::MimeType cHeaderTy = db->findByType(QLatin1String("text/x-hdr"));
Core::MimeType cppHeaderTy = db->findByType(QLatin1String("text/x-c++hdr"));
foreach (const QString &file, files) {
const QFileInfo fileInfo(file);
if (cSourceTy.matchesFile(fileInfo) || cppSourceTy.matchesFile(fileInfo) || mSourceTy.matchesFile(fileInfo))
sources.append(file);
else if (cHeaderTy.matchesFile(fileInfo) || cppHeaderTy.matchesFile(fileInfo))
headers.append(file);
}
foreach (const QString &file, files) {
preproc->snapshot.remove(file);
}
QStringList sources;
QStringList headers;
const Core::MimeDatabase *mimeDb = Core::ICore::instance()->mimeDatabase();
mimeDb->findByFile(files.constBegin(), files.constEnd(),
HeaderSourceSorter(&sources, &headers));
const int sourceCount = sources.size();
files = sources;
files += headers;
foreach (const QString &file, files)
preproc->snapshot.remove(file);
preproc->setTodo(files);
......@@ -1278,12 +1299,9 @@ void CppModelManager::parse(QFutureInterface<void> &future,
// Change the priority of the background parser thread to idle.
QThread::currentThread()->setPriority(QThread::IdlePriority);
QString fileName = files.at(i);
bool isSourceFile = false;
if (cppSourceTy.matchesFile(fileName) || cSourceTy.matchesFile(fileName))
isSourceFile = true;
const QString fileName = files.at(i);
const bool isSourceFile = i < sourceCount;
if (isSourceFile)
(void) preproc->run(conf);
......
Supports Markdown
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