12 changed files with 183 additions and 46 deletions
@ -0,0 +1,33 @@
|
||||
#ifndef LIBREPOMGR_LOGCONTEXT_H |
||||
#define LIBREPOMGR_LOGCONTEXT_H |
||||
|
||||
// Do NOT include this header directly, include "loggin.h" instead. This header only exists to resolve the
|
||||
// cyclic dependency between LogContext and BuildAction but lacks definitions of operator().
|
||||
|
||||
#include "./global.h" |
||||
|
||||
#include <c++utilities/io/ansiescapecodes.h> |
||||
|
||||
namespace LibRepoMgr { |
||||
|
||||
struct BuildAction; |
||||
|
||||
struct LIBREPOMGR_EXPORT LogContext { |
||||
explicit LogContext(BuildAction *buildAction = nullptr); |
||||
LogContext &operator=(const LogContext &) = delete; |
||||
template <typename... Args> LogContext &operator()(CppUtilities::EscapeCodes::Phrases phrase, Args &&...args); |
||||
template <typename... Args> LogContext &operator()(Args &&...args); |
||||
template <typename... Args> LogContext &operator()(std::string &&msg); |
||||
|
||||
private: |
||||
BuildAction *const m_buildAction; |
||||
}; |
||||
|
||||
inline LogContext::LogContext(BuildAction *buildAction) |
||||
: m_buildAction(buildAction) |
||||
{ |
||||
} |
||||
|
||||
} // namespace LibRepoMgr
|
||||
|
||||
#endif // LIBREPOMGR_LOGCONTEXT_H
|
@ -0,0 +1,9 @@
|
||||
#include "./namedlockable.h" |
||||
#include "./logging.h" |
||||
|
||||
namespace LibRepoMgr { |
||||
|
||||
template struct NamedLock<std::shared_lock<std::shared_mutex>>; |
||||
template struct NamedLock<std::unique_lock<std::shared_mutex>>; |
||||
|
||||
} // namespace LibRepoMgr
|
@ -0,0 +1,105 @@
|
||||
#ifndef LIBREPOMGR_NAMED_LOCKABLE_H |
||||
#define LIBREPOMGR_NAMED_LOCKABLE_H |
||||
|
||||
#include <mutex> |
||||
#include <shared_mutex> |
||||
|
||||
#include "./global.h" |
||||
|
||||
namespace LibRepoMgr { |
||||
|
||||
struct LogContext; |
||||
|
||||
template <typename UnderlyingLockType> struct NamedLock { |
||||
template <typename... Args> NamedLock(LogContext &log, std::string &&name, Args &&...args); |
||||
NamedLock(NamedLock &&) = default; |
||||
~NamedLock(); |
||||
|
||||
const std::string &name() const |
||||
{ |
||||
return m_name; |
||||
}; |
||||
UnderlyingLockType &lock() |
||||
{ |
||||
return m_lock; |
||||
}; |
||||
|
||||
private: |
||||
LogContext &m_log; |
||||
std::string m_name; |
||||
UnderlyingLockType m_lock; |
||||
}; |
||||
|
||||
constexpr std::string_view lockName(std::shared_lock<std::shared_mutex> &) |
||||
{ |
||||
return "shared"; |
||||
} |
||||
constexpr std::string_view lockName(std::unique_lock<std::shared_mutex> &) |
||||
{ |
||||
return "exclusive"; |
||||
} |
||||
|
||||
template <typename UnderlyingLockType> |
||||
template <typename... Args> |
||||
inline NamedLock<UnderlyingLockType>::NamedLock(LogContext &log, std::string &&name, Args &&...args) |
||||
: m_log(log) |
||||
, m_name(std::move(name)) |
||||
{ |
||||
m_log("Acquiring ", lockName(m_lock), " lock \"", m_name, "\"\n"); |
||||
m_lock = UnderlyingLockType(std::forward<Args>(args)...); |
||||
} |
||||
|
||||
template <typename UnderlyingLockType> inline NamedLock<UnderlyingLockType>::~NamedLock() |
||||
{ |
||||
if (m_lock) { |
||||
m_lock.unlock(); |
||||
m_log("Released ", lockName(m_lock), " lock \"", m_name, "\"\n"); |
||||
} |
||||
} |
||||
|
||||
using SharedNamedLock = NamedLock<std::shared_lock<std::shared_mutex>>; |
||||
using UniqueNamedLock = NamedLock<std::unique_lock<std::shared_mutex>>; |
||||
|
||||
extern template struct LIBREPOMGR_EXPORT NamedLock<std::shared_lock<std::shared_mutex>>; |
||||
extern template struct LIBREPOMGR_EXPORT NamedLock<std::unique_lock<std::shared_mutex>>; |
||||
|
||||
struct NamedLockable { |
||||
[[nodiscard]] SharedNamedLock lockToRead(LogContext &log, std::string &&name) const; |
||||
[[nodiscard]] UniqueNamedLock lockToWrite(LogContext &log, std::string &&name); |
||||
[[nodiscard]] SharedNamedLock tryLockToRead(LogContext &log, std::string &&name) const; |
||||
[[nodiscard]] UniqueNamedLock tryLockToWrite(LogContext &log, std::string &&name); |
||||
[[nodiscard]] UniqueNamedLock lockToWrite(LogContext &log, std::string &&name, SharedNamedLock &readLock); |
||||
|
||||
private: |
||||
mutable std::shared_mutex m_mutex; |
||||
}; |
||||
|
||||
inline SharedNamedLock NamedLockable::lockToRead(LogContext &log, std::string &&name) const |
||||
{ |
||||
return SharedNamedLock(log, std::move(name), m_mutex); |
||||
} |
||||
|
||||
inline UniqueNamedLock NamedLockable::lockToWrite(LogContext &log, std::string &&name) |
||||
{ |
||||
return UniqueNamedLock(log, std::move(name), m_mutex); |
||||
} |
||||
|
||||
inline SharedNamedLock NamedLockable::tryLockToRead(LogContext &log, std::string &&name) const |
||||
{ |
||||
return SharedNamedLock(log, std::move(name), m_mutex, std::try_to_lock); |
||||
} |
||||
|
||||
inline UniqueNamedLock NamedLockable::tryLockToWrite(LogContext &log, std::string &&name) |
||||
{ |
||||
return UniqueNamedLock(log, std::move(name), m_mutex, std::try_to_lock); |
||||
} |
||||
|
||||
inline UniqueNamedLock NamedLockable::lockToWrite(LogContext &log, std::string &&name, SharedNamedLock &readLock) |
||||
{ |
||||
readLock.lock().unlock(); |
||||
return UniqueNamedLock(log, std::move(name), m_mutex); |
||||
} |
||||
|
||||
} // namespace LibRepoMgr
|
||||
|
||||
#endif // LIBREPOMGR_NAMED_LOCKABLE_H
|
Loading…
Reference in new issue