From c962b8c2df8e8a2cbbb7fc4eceebc37bcf3506b9 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 5 Jun 2019 17:27:10 +0200 Subject: [PATCH] QWaylandDisplay: replace a QMap, pointer*> with a std::vector<{QString, int, unique_ptr}> The vector is sorted, so lookup performance is the same, or better. Insertion performance is worse, of course, at least in big-O terms, but probably not in practice. But now the good part: saves a stunning 7.2KiB (0.6%) in text size on optimized AMD 64 Linux GCC 9.1 builds. Change-Id: Ie604f83d7d51111430db1d0bb89d8cc3a52301bf Reviewed-by: Lars Knoll --- .../platforms/wayland/qwaylandcursor.cpp | 4 +-- .../platforms/wayland/qwaylandcursor_p.h | 4 ++- .../platforms/wayland/qwaylanddisplay.cpp | 31 ++++++++++++++----- .../platforms/wayland/qwaylanddisplay_p.h | 17 +++++++++- 4 files changed, 45 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/wayland/qwaylandcursor.cpp b/src/plugins/platforms/wayland/qwaylandcursor.cpp index c9e3eb9ca88..5a6ab44bc73 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor.cpp +++ b/src/plugins/platforms/wayland/qwaylandcursor.cpp @@ -54,7 +54,7 @@ QT_BEGIN_NAMESPACE namespace QtWaylandClient { -QWaylandCursorTheme *QWaylandCursorTheme::create(QWaylandShm *shm, int size, const QString &themeName) +std::unique_ptr QWaylandCursorTheme::create(QWaylandShm *shm, int size, const QString &themeName) { QByteArray nameBytes = themeName.toLocal8Bit(); struct ::wl_cursor_theme *theme = wl_cursor_theme_load(nameBytes.constData(), size, shm->object()); @@ -64,7 +64,7 @@ QWaylandCursorTheme *QWaylandCursorTheme::create(QWaylandShm *shm, int size, con return nullptr; } - return new QWaylandCursorTheme(theme); + return std::unique_ptr{new QWaylandCursorTheme(theme)}; } QWaylandCursorTheme::~QWaylandCursorTheme() diff --git a/src/plugins/platforms/wayland/qwaylandcursor_p.h b/src/plugins/platforms/wayland/qwaylandcursor_p.h index 3e5cff9bca1..de96c22b233 100644 --- a/src/plugins/platforms/wayland/qwaylandcursor_p.h +++ b/src/plugins/platforms/wayland/qwaylandcursor_p.h @@ -57,6 +57,8 @@ #if QT_CONFIG(cursor) +#include + struct wl_cursor; struct wl_cursor_image; struct wl_cursor_theme; @@ -73,7 +75,7 @@ class QWaylandShm; class Q_WAYLAND_CLIENT_EXPORT QWaylandCursorTheme { public: - static QWaylandCursorTheme *create(QWaylandShm *shm, int size, const QString &themeName); + static std::unique_ptr create(QWaylandShm *shm, int size, const QString &themeName); ~QWaylandCursorTheme(); ::wl_cursor *cursor(Qt::CursorShape shape); diff --git a/src/plugins/platforms/wayland/qwaylanddisplay.cpp b/src/plugins/platforms/wayland/qwaylanddisplay.cpp index 37cb0e9bc41..11af5f58950 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay.cpp +++ b/src/plugins/platforms/wayland/qwaylanddisplay.cpp @@ -85,6 +85,8 @@ #include +#include // for std::tie + QT_BEGIN_NAMESPACE namespace QtWaylandClient { @@ -183,7 +185,7 @@ QWaylandDisplay::~QWaylandDisplay(void) delete mDndSelectionHandler.take(); #endif #if QT_CONFIG(cursor) - qDeleteAll(mCursorThemes); + mCursorThemes.clear(); #endif if (mDisplay) wl_display_disconnect(mDisplay); @@ -602,15 +604,30 @@ QWaylandCursor *QWaylandDisplay::waylandCursor() return mCursor.data(); } +auto QWaylandDisplay::findExistingCursorTheme(const QString &name, int pixelSize) const noexcept + -> FindExistingCursorThemeResult +{ + const auto byNameAndSize = [](const WaylandCursorTheme &lhs, const WaylandCursorTheme &rhs) { + return std::tie(lhs.pixelSize, lhs.name) < std::tie(rhs.pixelSize, rhs.name); + }; + + const WaylandCursorTheme prototype = {name, pixelSize, nullptr}; + + const auto it = std::lower_bound(mCursorThemes.cbegin(), mCursorThemes.cend(), prototype, byNameAndSize); + if (it != mCursorThemes.cend() && it->name == name && it->pixelSize == pixelSize) + return {it, true}; + else + return {it, false}; +} + QWaylandCursorTheme *QWaylandDisplay::loadCursorTheme(const QString &name, int pixelSize) { - if (auto *theme = mCursorThemes.value({name, pixelSize}, nullptr)) - return theme; + const auto result = findExistingCursorTheme(name, pixelSize); + if (result.found) + return result.theme(); - if (auto *theme = QWaylandCursorTheme::create(shm(), pixelSize, name)) { - mCursorThemes[{name, pixelSize}] = theme; - return theme; - } + if (auto theme = QWaylandCursorTheme::create(shm(), pixelSize, name)) + return mCursorThemes.insert(result.position, {name, pixelSize, std::move(theme)})->theme.get(); return nullptr; } diff --git a/src/plugins/platforms/wayland/qwaylanddisplay_p.h b/src/plugins/platforms/wayland/qwaylanddisplay_p.h index a52c89fe9c7..83a56556e33 100644 --- a/src/plugins/platforms/wayland/qwaylanddisplay_p.h +++ b/src/plugins/platforms/wayland/qwaylanddisplay_p.h @@ -238,7 +238,22 @@ private: QList mRegistryListeners; QWaylandIntegration *mWaylandIntegration = nullptr; #if QT_CONFIG(cursor) - QMap, QWaylandCursorTheme *> mCursorThemes; // theme name and size + struct WaylandCursorTheme { + QString name; + int pixelSize; + std::unique_ptr theme; + }; + std::vector mCursorThemes; + + struct FindExistingCursorThemeResult { + std::vector::const_iterator position; + bool found; + + QWaylandCursorTheme *theme() const noexcept + { return found ? position->theme.get() : nullptr; } + }; + FindExistingCursorThemeResult findExistingCursorTheme(const QString &name, int pixelSize) const; + QScopedPointer mCursor; #endif #if QT_CONFIG(wayland_datadevice)