Implement helper functions for async global locks
This commit is contained in:
parent
e74f80a089
commit
8dfa948e03
|
@ -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})
|
||||
|
||||
|
|
|
@ -18,12 +18,12 @@ struct LogContext;
|
|||
struct GlobalSharedMutex {
|
||||
void lock();
|
||||
bool try_lock();
|
||||
void lock_async(std::function<void()> &&callback);
|
||||
void lock_async(std::move_only_function<void()> &&callback);
|
||||
void unlock();
|
||||
|
||||
void lock_shared();
|
||||
bool try_lock_shared();
|
||||
void lock_shared_async(std::function<void()> &&callback);
|
||||
void lock_shared_async(std::move_only_function<void()> &&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<std::function<void()>> m_sharedCallbacks;
|
||||
std::function<void()> m_exclusiveCallback;
|
||||
std::list<std::move_only_function<void()>> m_sharedCallbacks;
|
||||
std::move_only_function<void()> m_exclusiveCallback;
|
||||
};
|
||||
|
||||
inline void GlobalSharedMutex::lock()
|
||||
|
@ -56,7 +56,7 @@ inline bool GlobalSharedMutex::try_lock()
|
|||
}
|
||||
}
|
||||
|
||||
inline void GlobalSharedMutex::lock_async(std::function<void()> &&callback)
|
||||
inline void GlobalSharedMutex::lock_async(std::move_only_function<void()> &&callback)
|
||||
{
|
||||
auto lock = std::unique_lock<std::mutex>(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<void()> &&callback)
|
||||
inline void GlobalSharedMutex::lock_shared_async(std::move_only_function<void()> &&callback)
|
||||
{
|
||||
auto lock = std::unique_lock<std::mutex>(m_mutex);
|
||||
if (m_exclusivelyOwned) {
|
||||
|
@ -143,7 +143,9 @@ inline void GlobalSharedMutex::notify(std::unique_lock<std::mutex> &lock)
|
|||
|
||||
/// \brief A wrapper around a standard lock which logs acquisition/release.
|
||||
template <typename UnderlyingLockType> struct LoggingLock {
|
||||
template <typename... Args> LoggingLock(LogContext &log, std::string &&name, Args &&...args);
|
||||
using LockType = UnderlyingLockType;
|
||||
explicit LoggingLock(LogContext &log, std::string &&name);
|
||||
template <typename... Args> 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<GlobalSharedMutex> &)
|
|||
return "exclusive";
|
||||
}
|
||||
|
||||
template <typename UnderlyingLockType>
|
||||
inline LoggingLock<UnderlyingLockType>::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 <typename UnderlyingLockType>
|
||||
template <typename... Args>
|
||||
inline LoggingLock<UnderlyingLockType>::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<void(SharedLoggingLock &&lock)> &&callback) const;
|
||||
void lockToWrite(LogContext &log, std::string &&name, std::move_only_function<void(UniqueLoggingLock &&lock)> &&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<void(SharedLoggingLock &&)> &&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<void(UniqueLoggingLock &&)> &&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
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include <boost/asio/ip/address.hpp>
|
||||
#include <boost/asio/ssl/context.hpp>
|
||||
|
||||
#include <functional>
|
||||
#include <memory>
|
||||
#include <thread>
|
||||
#include <vector>
|
||||
|
@ -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<LockTable *, std::unique_lock<std::shared_mutex>> acquireLockTable();
|
||||
void acquireToRead(LogContext &log, std::string &&name, std::move_only_function<void(SharedLoggingLock &&lock)> &&callback);
|
||||
void acquireToWrite(LogContext &log, std::string &&name, std::move_only_function<void(UniqueLoggingLock &&lock)> &&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<void(SharedLoggingLock &&lock)> &&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<void(UniqueLoggingLock &&lock)> &&callback)
|
||||
{
|
||||
const auto locktableLock = std::shared_lock(m_cleanupMutex);
|
||||
namedLock(lockName).lockToWrite(log, std::move(lockName), std::move(callback));
|
||||
}
|
||||
|
||||
inline std::pair<ServiceSetup::Locks::LockTable *, std::unique_lock<std::shared_mutex>> ServiceSetup::Locks::acquireLockTable()
|
||||
{
|
||||
return std::make_pair(&m_locksByName, std::unique_lock(m_cleanupMutex));
|
||||
|
|
Loading…
Reference in New Issue