18 #ifndef CSLIBGUARDED_SHARED_GUARDED_H
19 #define CSLIBGUARDED_SHARED_GUARDED_H
23 #include <shared_mutex>
41 template <
typename T,
typename M = std::shared_timed_mutex,
typename L = std::shared_lock<M>>
49 using handle = std::unique_ptr<T, deleter>;
50 using shared_handle = std::unique_ptr<
const T, shared_deleter>;
52 template <
typename... Us>
53 shared_guarded(Us &&... data);
56 [[nodiscard]] handle lock();
57 [[nodiscard]] handle try_lock();
59 template <
class Duration>
60 [[nodiscard]] handle try_lock_for(
const Duration &duration);
62 template <
class TimePoint>
63 [[nodiscard]] handle try_lock_until(
const TimePoint &timepoint);
66 [[nodiscard]] shared_handle lock_shared()
const;
67 [[nodiscard]] shared_handle try_lock_shared()
const;
69 template <
class Duration>
70 [[nodiscard]] shared_handle try_lock_shared_for(
const Duration &duration)
const;
72 template <
class TimePoint>
73 [[nodiscard]] shared_handle try_lock_shared_until(
const TimePoint &timepoint)
const;
80 template <
typename T,
typename M,
typename L>
81 class shared_guarded<T, M, L>::deleter
87 deleter(std::unique_lock<M> lock);
89 void operator()(T *ptr);
92 std::unique_lock<M> m_lock;
95 template <
typename T,
typename M,
typename L>
96 shared_guarded<T, M, L>::deleter::deleter(std::unique_lock<M> lock)
97 : m_lock(std::move(lock))
101 template <
typename T,
typename M,
typename L>
102 void shared_guarded<T, M, L>::deleter::operator()(T *)
104 if (m_lock.owns_lock()) {
109 template <
typename T,
typename M,
typename L>
110 class shared_guarded<T, M, L>::shared_deleter
113 using pointer =
const T *;
115 shared_deleter() =
default;
116 shared_deleter(L lock);
118 void operator()(
const T *ptr);
124 template <
typename T,
typename M,
typename L>
125 shared_guarded<T, M, L>::shared_deleter::shared_deleter(L lock)
126 : m_lock(std::move(lock))
130 template <
typename T,
typename M,
typename L>
131 void shared_guarded<T, M, L>::shared_deleter::operator()(
const T *)
133 if (m_lock.owns_lock()) {
138 template <
typename T,
typename M,
typename L>
139 template <
typename... Us>
140 shared_guarded<T, M, L>::shared_guarded(Us &&... data)
141 : m_obj(std::forward<Us>(data)...)
145 template <
typename T,
typename M,
typename L>
146 auto shared_guarded<T, M, L>::lock() -> handle
148 std::unique_lock<M> lock(m_mutex);
149 return handle(&m_obj, deleter(std::move(lock)));
152 template <
typename T,
typename M,
typename L>
153 auto shared_guarded<T, M, L>::try_lock() -> handle
155 std::unique_lock<M> lock(m_mutex, std::try_to_lock);
157 if (lock.owns_lock()) {
158 return handle(&m_obj, deleter(std::move(lock)));
160 return handle(
nullptr, deleter(std::move(lock)));
164 template <
typename T,
typename M,
typename L>
165 template <
typename Duration>
166 auto shared_guarded<T, M, L>::try_lock_for(
const Duration &duration) -> handle
168 std::unique_lock<M> lock(m_mutex, duration);
170 if (lock.owns_lock()) {
171 return handle(&m_obj, deleter(std::move(lock)));
173 return handle(
nullptr, deleter(std::move(lock)));
177 template <
typename T,
typename M,
typename L>
178 template <
typename TimePoint>
179 auto shared_guarded<T, M, L>::try_lock_until(
const TimePoint &timepoint) -> handle
181 std::unique_lock<M> lock(m_mutex, timepoint);
183 if (lock.owns_lock()) {
184 return handle(&m_obj, deleter(std::move(lock)));
186 return handle(
nullptr, deleter(std::move(lock)));
190 template <
typename T,
typename M,
typename L>
191 auto shared_guarded<T, M, L>::lock_shared()
const -> shared_handle
194 return shared_handle(&m_obj, shared_deleter(std::move(lock)));
197 template <
typename T,
typename M,
typename L>
198 auto shared_guarded<T, M, L>::try_lock_shared()
const -> shared_handle
200 L lock(m_mutex, std::try_to_lock);
202 if (lock.owns_lock()) {
203 return shared_handle(&m_obj, shared_deleter(std::move(lock)));
205 return shared_handle(
nullptr, shared_deleter(std::move(lock)));
209 template <
typename T,
typename M,
typename L>
210 template <
typename Duration>
211 auto shared_guarded<T, M, L>::try_lock_shared_for(
const Duration &d)
const -> shared_handle
215 if (lock.owns_lock()) {
216 return shared_handle(&m_obj, shared_deleter(std::move(lock)));
218 return shared_handle(
nullptr, shared_deleter(std::move(lock)));
222 template <
typename T,
typename M,
typename L>
223 template <
typename TimePoint>
224 auto shared_guarded<T, M, L>::try_lock_shared_until(
const TimePoint &tp)
const -> shared_handle
228 if (lock.owns_lock()) {
229 return shared_handle(&m_obj, shared_deleter(std::move(lock)));
231 return shared_handle(
nullptr, shared_deleter(std::move(lock)));