diff --git a/librepomgr/serversetup.cpp b/librepomgr/serversetup.cpp index af4ed93..fe274df 100644 --- a/librepomgr/serversetup.cpp +++ b/librepomgr/serversetup.cpp @@ -660,7 +660,7 @@ void ServiceSetup::run() void ServiceSetup::Locks::clear() { auto log = LogContext(); - const auto lock = std::lock_guard(m_mutex); + const auto lock = std::unique_lock(m_cleanupMutex); for (auto i = m_locksByName.begin(), end = m_locksByName.end(); i != end;) { if (auto lock2 = i->second.tryLockToWrite(log, std::string(i->first)); lock2.lock()) { // check whether nobody holds the lock anymore lock2.lock().unlock(); // ~shared_mutex(): The behavior is undefined if the mutex is owned by any thread [...]. diff --git a/librepomgr/serversetup.h b/librepomgr/serversetup.h index 86a306b..51ac318 100644 --- a/librepomgr/serversetup.h +++ b/librepomgr/serversetup.h @@ -127,15 +127,17 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable { struct LIBREPOMGR_EXPORT Locks { using LockTable = std::unordered_map; + [[nodiscard]] GlobalLockable &namedLock(const std::string &lockName); [[nodiscard]] SharedLoggingLock acquireToRead(LogContext &log, std::string &&lockName); [[nodiscard]] UniqueLoggingLock acquireToWrite(LogContext &log, std::string &&lockName); - [[nodiscard]] std::pair> acquireLockTable(); + [[nodiscard]] std::pair> acquireLockTable(); void clear(); static std::string forDatabase(std::string_view dbName, std::string_view dbArch); static std::string forDatabase(const LibPkg::Database &db); private: - std::mutex m_mutex; + std::mutex m_accessMutex; + std::shared_mutex m_cleanupMutex; LockTable m_locksByName; } locks; @@ -155,21 +157,27 @@ inline std::shared_ptr ServiceSetup::BuildSetup::getBuildAction(Bui return id < actions.size() ? actions[id] : nullptr; } +inline GlobalLockable &ServiceSetup::Locks::namedLock(const std::string &lockName) +{ + const auto locktableLock = std::unique_lock(m_accessMutex); + return m_locksByName[lockName]; +} + inline SharedLoggingLock ServiceSetup::Locks::acquireToRead(LogContext &log, std::string &&lockName) { - const auto lock = std::lock_guard(m_mutex); - return m_locksByName[lockName].lockToRead(log, std::move(lockName)); + const auto locktableLock = std::shared_lock(m_cleanupMutex); + return namedLock(lockName).lockToRead(log, std::move(lockName)); } inline UniqueLoggingLock ServiceSetup::Locks::acquireToWrite(LogContext &log, std::string &&lockName) { - const auto lock = std::lock_guard(m_mutex); - return m_locksByName[lockName].lockToWrite(log, std::move(lockName)); + const auto locktableLock = std::shared_lock(m_cleanupMutex); + return namedLock(lockName).lockToWrite(log, std::move(lockName)); } -inline std::pair> ServiceSetup::Locks::acquireLockTable() +inline std::pair> ServiceSetup::Locks::acquireLockTable() { - return std::make_pair(&m_locksByName, std::unique_lock(m_mutex)); + return std::make_pair(&m_locksByName, std::unique_lock(m_cleanupMutex)); } struct LIBREPOMGR_EXPORT ServiceStatus : public ReflectiveRapidJSON::JsonSerializable {