diff --git a/CMakeLists.txt b/CMakeLists.txt index 4f09638..37a015a 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -11,7 +11,9 @@ set(META_VERSION_MAJOR 0) set(META_VERSION_MINOR 0) set(META_VERSION_PATCH 3) set(META_VERSION_EXACT_SONAME ON) -set(META_CXX_STANDARD 20) +#set(META_CXX_STANDARD 20) +set(META_CXX_STANDARD "any") +list(APPEND META_PUBLIC_COMPILE_OPTIONS "-std=c++2b") project(${META_PROJECT_NAME}) diff --git a/librepomgr/globallock.h b/librepomgr/globallock.h index 64da977..11899bc 100644 --- a/librepomgr/globallock.h +++ b/librepomgr/globallock.h @@ -18,12 +18,12 @@ struct LogContext; struct GlobalSharedMutex { void lock(); bool try_lock(); - void lock_async(std::function &&callback); + void lock_async(std::move_only_function &&callback); void unlock(); void lock_shared(); bool try_lock_shared(); - void lock_shared_async(std::function &&callback); + void lock_shared_async(std::move_only_function &&callback); void unlock_shared(); private: @@ -33,8 +33,8 @@ private: std::condition_variable m_cv; std::uint32_t m_sharedOwners = 0; bool m_exclusivelyOwned = false; - std::list> m_sharedCallbacks; - std::function m_exclusiveCallback; + std::list> m_sharedCallbacks; + std::move_only_function m_exclusiveCallback; }; inline void GlobalSharedMutex::lock() @@ -56,7 +56,7 @@ inline bool GlobalSharedMutex::try_lock() } } -inline void GlobalSharedMutex::lock_async(std::function &&callback) +inline void GlobalSharedMutex::lock_async(std::move_only_function &&callback) { auto lock = std::unique_lock(m_mutex); if (m_sharedOwners || m_exclusivelyOwned) { @@ -94,7 +94,7 @@ inline bool GlobalSharedMutex::try_lock_shared() } } -inline void GlobalSharedMutex::lock_shared_async(std::function &&callback) +inline void GlobalSharedMutex::lock_shared_async(std::move_only_function &&callback) { auto lock = std::unique_lock(m_mutex); if (m_exclusivelyOwned) { @@ -143,7 +143,9 @@ inline void GlobalSharedMutex::notify(std::unique_lock &lock) /// \brief A wrapper around a standard lock which logs acquisition/release. template struct LoggingLock { - template LoggingLock(LogContext &log, std::string &&name, Args &&...args); + using LockType = UnderlyingLockType; + explicit LoggingLock(LogContext &log, std::string &&name); + template explicit LoggingLock(LogContext &log, std::string &&name, Args &&...args); LoggingLock(LoggingLock &&) = default; ~LoggingLock(); @@ -171,6 +173,14 @@ constexpr std::string_view lockName(std::unique_lock &) return "exclusive"; } +template +inline LoggingLock::LoggingLock(LogContext &log, std::string &&name) + : m_log(log) + , m_name(std::move(name)) +{ + m_log("Acquiring ", lockName(m_lock), " lock \"", m_name, "\"\n"); +} + template template inline LoggingLock::LoggingLock(LogContext &log, std::string &&name, Args &&...args) @@ -202,6 +212,8 @@ struct GlobalLockable { [[nodiscard]] SharedLoggingLock tryLockToRead(LogContext &log, std::string &&name) const; [[nodiscard]] UniqueLoggingLock tryLockToWrite(LogContext &log, std::string &&name); [[nodiscard]] UniqueLoggingLock lockToWrite(LogContext &log, std::string &&name, SharedLoggingLock &readLock); + void lockToRead(LogContext &log, std::string &&name, std::move_only_function &&callback) const; + void lockToWrite(LogContext &log, std::string &&name, std::move_only_function &&callback); private: mutable GlobalSharedMutex m_mutex; @@ -233,6 +245,24 @@ inline UniqueLoggingLock GlobalLockable::lockToWrite(LogContext &log, std::strin return UniqueLoggingLock(log, std::move(name), m_mutex); } +inline void LibRepoMgr::GlobalLockable::lockToRead( + LogContext &log, std::string &&name, std::move_only_function &&callback) const +{ + m_mutex.lock_shared_async([this, lock = SharedLoggingLock(log, std::move(name)), cb = std::move(callback)]() mutable { + lock.lock() = SharedLoggingLock::LockType(m_mutex, std::adopt_lock); + cb(std::move(lock)); + }); +} + +inline void LibRepoMgr::GlobalLockable::lockToWrite( + LogContext &log, std::string &&name, std::move_only_function &&callback) +{ + m_mutex.lock_async([this, lock = UniqueLoggingLock(log, std::move(name)), cb = std::move(callback)]() mutable { + lock.lock() = UniqueLoggingLock::LockType(m_mutex, std::adopt_lock); + cb(std::move(lock)); + }); +} + } // namespace LibRepoMgr #endif // LIBREPOMGR_GLOBAL_LOCK_H diff --git a/librepomgr/serversetup.h b/librepomgr/serversetup.h index 01e508b..d24914a 100644 --- a/librepomgr/serversetup.h +++ b/librepomgr/serversetup.h @@ -16,6 +16,7 @@ #include #include +#include #include #include #include @@ -178,6 +179,8 @@ struct LIBREPOMGR_EXPORT ServiceSetup : public LibPkg::Lockable { [[nodiscard]] SharedLoggingLock acquireToRead(LogContext &log, std::string &&lockName); [[nodiscard]] UniqueLoggingLock acquireToWrite(LogContext &log, std::string &&lockName); [[nodiscard]] std::pair> acquireLockTable(); + void acquireToRead(LogContext &log, std::string &&name, std::move_only_function &&callback); + void acquireToWrite(LogContext &log, std::string &&name, std::move_only_function &&callback); void clear(); static std::string forDatabase(std::string_view dbName, std::string_view dbArch); static std::string forDatabase(const LibPkg::Database &db); @@ -217,6 +220,20 @@ inline UniqueLoggingLock ServiceSetup::Locks::acquireToWrite(LogContext &log, st return namedLock(lockName).lockToWrite(log, std::move(lockName)); } +inline void ServiceSetup::Locks::acquireToRead( + LogContext &log, std::string &&lockName, std::move_only_function &&callback) +{ + const auto locktableLock = std::shared_lock(m_cleanupMutex); + namedLock(lockName).lockToRead(log, std::move(lockName), std::move(callback)); +} + +inline void ServiceSetup::Locks::acquireToWrite( + LogContext &log, std::string &&lockName, std::move_only_function &&callback) +{ + const auto locktableLock = std::shared_lock(m_cleanupMutex); + namedLock(lockName).lockToWrite(log, std::move(lockName), std::move(callback)); +} + inline std::pair> ServiceSetup::Locks::acquireLockTable() { return std::make_pair(&m_locksByName, std::unique_lock(m_cleanupMutex));