Add fast-path in QLibraryStore::findOrCreate() for empty fileName

The LibraryMap can never contain an object whose fileName is empty.

To see that, observe that the only insertion into LibraryMap is in
findOrCreate() and that refuses to add such objects there.

But if LibraryMap cannot contain such an object, and findOrCreate({})
is just an ugly way to get a default-constructed QLibraryPrivate (a
new one for each call), then we don't need to lock the
qt_library_mutex to produce one, and neither do we need to construct a
mapName that we know we'll not find, anyway.

So drag this case to before the mutex locking and the construction of
mapName.

It took me more coffee than I'm ready to admit to figure this out, so
leave a comment for the next reader indicating that an empty fileName
is actually a valid argument.

To avoid repeating the new-expression, wrap it in a lambda, together
with the ref() call. Move the remaining ref() call to where it's still
needed.

The final goal of this exercise is to get rid of the double-lookup in
LibraryMap.

Pick-to: 6.6 6.5
Change-Id: I781eafdb9516410d7a262ad27f52c38ad2742292
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
(cherry picked from commit b28bad0b20719f72fb335a65f76382132e326ad0)
Reviewed-by: Qt Cherry-pick Bot <cherrypick_bot@qt-project.org>
This commit is contained in:
Marc Mutz 2024-02-07 21:32:20 +01:00 committed by Qt Cherry-pick Bot
parent c052ee9032
commit fbb2bd0a25

View File

@ -395,6 +395,15 @@ QLibraryStore *QLibraryStore::instance()
inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version, inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, const QString &version,
QLibrary::LoadHints loadHints) QLibrary::LoadHints loadHints)
{ {
auto lazyNewLib = [&] {
auto result = new QLibraryPrivate(fileName, version, loadHints);
result->libraryRefCount.ref();
return result;
};
if (fileName.isEmpty()) // request for empty d-pointer in QLibrary::setLoadHints();
return lazyNewLib(); // must return an independent (new) object
QMutexLocker locker(&qt_library_mutex); QMutexLocker locker(&qt_library_mutex);
QLibraryStore *data = instance(); QLibraryStore *data = instance();
@ -404,17 +413,18 @@ inline QLibraryPrivate *QLibraryStore::findOrCreate(const QString &fileName, con
QLibraryPrivate *lib = nullptr; QLibraryPrivate *lib = nullptr;
if (Q_LIKELY(data)) { if (Q_LIKELY(data)) {
lib = data->libraryMap.value(mapName); lib = data->libraryMap.value(mapName);
if (lib) if (lib) {
lib->libraryRefCount.ref();
lib->mergeLoadHints(loadHints); lib->mergeLoadHints(loadHints);
}
} }
if (!lib) if (!lib)
lib = new QLibraryPrivate(fileName, version, loadHints); lib = lazyNewLib();
// track this library // track this library
if (Q_LIKELY(data) && !fileName.isEmpty()) if (Q_LIKELY(data))
data->libraryMap.insert(mapName, lib); data->libraryMap.insert(mapName, lib);
lib->libraryRefCount.ref();
return lib; return lib;
} }