18 #ifndef CSLIBGUARDED_LOCK_GUARDS_H
19 #define CSLIBGUARDED_LOCK_GUARDS_H
37 constexpr guard_address(
const T &object) : value(&object){};
39 const void *
const value;
43 class guard_locker_base
46 guard_locker_base(
const void *address) : m_address(address){};
48 virtual ~guard_locker_base() =
default;
50 [[nodiscard]]
virtual bool do_try_lock() = 0;
51 virtual void reset() = 0;
53 [[nodiscard]]
bool operator<(
const guard_locker_base &rhs)
const noexcept
55 return m_address < rhs.m_address;
59 const void *
const m_address;
65 class guard_locker :
public guard_locker_base
68 using lock_type = std::decay_t<
decltype(std::declval<T>().try_lock())>;
70 guard_locker(T &guard) : guard_locker_base(guard_address<T>(guard).value), m_guard(guard)
74 [[nodiscard]]
bool do_try_lock()
override
76 m_lock = m_guard.try_lock();
77 return m_lock !=
nullptr;
85 [[nodiscard]] lock_type take_lock() &&
87 return std::move(m_lock);
101 guard_reader(T &guard) : m_guard(guard)
105 [[nodiscard]]
auto try_lock()
107 return m_guard.try_lock_shared();
113 friend class guard_address<guard_reader<T>>;
118 template <
typename T>
119 class guard_address<guard_reader<T>>
122 constexpr guard_address(
const guard_reader<T> &object) : value(&(object.m_guard)){};
124 const void *
const value;
129 template <
typename T>
130 [[nodiscard]]
auto as_reader(T &guard)
132 return detail::guard_reader<T>(guard);
135 template <
typename... Ts>
136 [[nodiscard]]
auto lock_guards(Ts &&...Vs)
138 using namespace libguarded::detail;
140 std::tuple<guard_locker<Ts>...> lockers = {guard_locker<Ts>(Vs)...};
142 auto lock_sequence = std::apply(
144 std::array<guard_locker_base *,
sizeof...(Ts)> retval = {(&args)...};
150 std::sort(lock_sequence.begin(), lock_sequence.end());
152 auto iter = lock_sequence.begin();
155 while (iter != lock_sequence.end()) {
156 if ((*iter)->do_try_lock()) {
161 while (iter != lock_sequence.begin()) {
173 return std::make_tuple(std::move(args).take_lock()...);