qmake: fix file id mapping lifetime management

turns out that flushing the ids together with the ProFile cache was an
abysmal idea, as the latter expires after a few seconds after loading
the project, while references to the ProFiles (and thus the underlying
file ids) are kept for as long as the project stays loaded. the early
flush would cause re-use of the file ids, which would wreak all kinds of
havoc when re-loading projects.

but just ref-counting the vfs class is insufficient as well, as then the
ProFile cache (which expires after a timeout) could outlive all VFS
instances and thus refer to ids which were discarded and later re-used.

so we ref-count, and additionally let the cache instance hold a
reference to the vfs class.

this is sync-up with qt creator; no actual effect on qmake itself.

amends 190aa94be.

Change-Id: Idd4478ffc1c2405b3b83df32fba45b1f687f6a18
Reviewed-by: Robert Loehning <robert.loehning@qt.io>
Reviewed-by: Orgad Shaneh <orgads@gmail.com>
Reviewed-by: Eike Ziller <eike.ziller@qt.io>
Reviewed-by: Tobias Hunger <tobias.hunger@qt.io>
(cherry picked from qtcreator/d03fb350672d311dccc06f0bcb4da744a3c99745)
(cherry picked from qtcreator/1ddfb443b686ef04cc0e28363308ce70d01f0d73)
Reviewed-by: Oswald Buddenhagen <oswald.buddenhagen@qt.io>
This commit is contained in:
Oswald Buddenhagen 2018-05-24 20:50:32 +02:00
parent 39cb9ac873
commit f12fd482f5
4 changed files with 39 additions and 12 deletions

View File

@ -45,11 +45,17 @@ QT_BEGIN_NAMESPACE
//
///////////////////////////////////////////////////////////////////////
ProFileCache::ProFileCache()
{
QMakeVfs::ref();
}
ProFileCache::~ProFileCache()
{
for (const Entry &ent : qAsConst(parsed_files))
if (ent.pro)
ent.pro->deref();
QMakeVfs::deref();
}
void ProFileCache::discardFile(const QString &fileName, QMakeVfs *vfs)

View File

@ -201,7 +201,7 @@ Q_DECLARE_OPERATORS_FOR_FLAGS(QMakeParser::ParseFlags)
class QMAKE_EXPORT ProFileCache
{
public:
ProFileCache() {}
ProFileCache();
~ProFileCache();
void discardFile(int id);

View File

@ -52,11 +52,38 @@ QMakeVfs::QMakeVfs()
#ifndef QT_NO_TEXTCODEC
m_textCodec = 0;
#endif
ref();
}
QMakeVfs::~QMakeVfs()
{
deref();
}
void QMakeVfs::ref()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
++s_refCount;
}
void QMakeVfs::deref()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
if (!--s_refCount) {
s_fileIdCounter = 0;
s_fileIdMap.clear();
s_idFileMap.clear();
}
}
#ifdef PROPARSER_THREAD_SAFE
QMutex QMakeVfs::s_mutex;
#endif
int QMakeVfs::s_refCount;
QAtomicInt QMakeVfs::s_fileIdCounter;
QHash<QString, int> QMakeVfs::s_fileIdMap;
QHash<int, QString> QMakeVfs::s_idFileMap;
@ -114,16 +141,6 @@ QString QMakeVfs::fileNameForId(int id)
return s_idFileMap.value(id);
}
void QMakeVfs::clearIds()
{
#ifdef PROEVALUATOR_THREAD_SAFE
QMutexLocker locker(&s_mutex);
#endif
s_fileIdCounter = 0;
s_fileIdMap.clear();
s_idFileMap.clear();
}
bool QMakeVfs::writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags,
const QString &contents, QString *errStr)
{

View File

@ -76,10 +76,13 @@ public:
Q_DECLARE_FLAGS(VfsFlags, VfsFlag)
QMakeVfs();
~QMakeVfs();
static void ref();
static void deref();
int idForFileName(const QString &fn, VfsFlags flags);
QString fileNameForId(int id);
static void clearIds();
bool writeFile(int id, QIODevice::OpenMode mode, VfsFlags flags, const QString &contents, QString *errStr);
ReadResult readFile(int id, QString *contents, QString *errStr);
bool exists(const QString &fn, QMakeVfs::VfsFlags flags);
@ -97,6 +100,7 @@ private:
#ifdef PROEVALUATOR_THREAD_SAFE
static QMutex s_mutex;
#endif
static int s_refCount;
static QAtomicInt s_fileIdCounter;
// Qt Creator's ProFile cache is a singleton to maximize its cross-project
// effectiveness (shared prf files from QtVersions).