18 #ifndef CSLIBGUARDED_PLAIN_GUARDED_H
19 #define CSLIBGUARDED_PLAIN_GUARDED_H
41 template <
typename T,
typename M = std::mutex>
49 using handle = std::unique_ptr<T, deleter>;
50 using const_handle = std::unique_ptr<
const T, const_deleter>;
57 template <
typename... Us>
58 plain_guarded(Us &&... data);
66 [[nodiscard]] handle lock();
67 [[nodiscard]] const_handle lock()
const;
76 [[nodiscard]] handle try_lock();
77 [[nodiscard]] const_handle try_lock()
const;
93 template <
class Duration>
94 [[nodiscard]] handle try_lock_for(
const Duration &duration);
95 template <
class Duration>
96 [[nodiscard]] const_handle try_lock_for(
const Duration &duration)
const;
111 template <
class TimePoint>
112 [[nodiscard]] handle try_lock_until(
const TimePoint &timepoint);
113 template <
class TimePoint>
114 [[nodiscard]] const_handle try_lock_until(
const TimePoint &timepoint)
const;
121 template <
typename T,
typename M>
122 class plain_guarded<T, M>::deleter
128 deleter(std::unique_lock<M> lock);
130 void operator()(T *ptr);
133 std::unique_lock<M> m_lock;
136 template <
typename T,
typename M>
137 plain_guarded<T, M>::deleter::deleter(std::unique_lock<M> lock)
138 : m_lock(std::move(lock))
142 template <
typename T,
typename M>
143 void plain_guarded<T, M>::deleter::operator()(T *)
145 if (m_lock.owns_lock()) {
150 template <
typename T,
typename M>
151 class plain_guarded<T, M>::const_deleter
154 using pointer =
const T *;
156 const_deleter() =
default;
157 const_deleter(std::unique_lock<M> lock);
159 void operator()(
const T *ptr);
162 std::unique_lock<M> m_lock;
165 template <
typename T,
typename M>
166 plain_guarded<T, M>::const_deleter::const_deleter(std::unique_lock<M> lock)
167 : m_lock(std::move(lock))
171 template <
typename T,
typename M>
172 void plain_guarded<T, M>::const_deleter::operator()(
const T *)
174 if (m_lock.owns_lock()) {
179 template <
typename T,
typename M>
180 template <
typename... Us>
181 plain_guarded<T, M>::plain_guarded(Us &&... data)
182 : m_obj(std::forward<Us>(data)...)
186 template <
typename T,
typename M>
187 auto plain_guarded<T, M>::lock() -> handle
189 std::unique_lock<M> lock(m_mutex);
190 return handle(&m_obj, deleter(std::move(lock)));
193 template <
typename T,
typename M>
194 auto plain_guarded<T, M>::lock()
const -> const_handle
196 std::unique_lock<M> lock(m_mutex);
197 return const_handle(&m_obj, const_deleter(std::move(lock)));
200 template <
typename T,
typename M>
201 auto plain_guarded<T, M>::try_lock() -> handle
203 std::unique_lock<M> lock(m_mutex, std::try_to_lock);
205 if (lock.owns_lock()) {
206 return handle(&m_obj, deleter(std::move(lock)));
208 return handle(
nullptr, deleter(std::move(lock)));
212 template <
typename T,
typename M>
213 auto plain_guarded<T, M>::try_lock()
const -> const_handle
215 std::unique_lock<M> lock(m_mutex, std::try_to_lock);
217 if (lock.owns_lock()) {
218 return const_handle(&m_obj, const_deleter(std::move(lock)));
220 return const_handle(
nullptr, const_deleter(std::move(lock)));
224 template <
typename T,
typename M>
225 template <
typename Duration>
226 auto plain_guarded<T, M>::try_lock_for(
const Duration &d) -> handle
228 std::unique_lock<M> lock(m_mutex, d);
230 if (lock.owns_lock()) {
231 return handle(&m_obj, deleter(std::move(lock)));
233 return handle(
nullptr, deleter(std::move(lock)));
237 template <
typename T,
typename M>
238 template <
typename Duration>
239 auto plain_guarded<T, M>::try_lock_for(
const Duration &d)
const -> const_handle
241 std::unique_lock<M> lock(m_mutex, d);
243 if (lock.owns_lock()) {
244 return const_handle(&m_obj, const_deleter(std::move(lock)));
246 return const_handle(
nullptr, const_deleter(std::move(lock)));
250 template <
typename T,
typename M>
251 template <
typename TimePoint>
252 auto plain_guarded<T, M>::try_lock_until(
const TimePoint &tp) -> handle
254 std::unique_lock<M> lock(m_mutex, tp);
256 if (lock.owns_lock()) {
257 return handle(&m_obj, deleter(std::move(lock)));
259 return handle(
nullptr, deleter(std::move(lock)));
263 template <
typename T,
typename M>
264 template <
typename TimePoint>
265 auto plain_guarded<T, M>::try_lock_until(
const TimePoint &tp)
const -> const_handle
267 std::unique_lock<M> lock(m_mutex, tp);
269 if (lock.owns_lock()) {
270 return const_handle(&m_obj, const_deleter(std::move(lock)));
272 return const_handle(
nullptr, const_deleter(std::move(lock)));
276 template <
typename T,
typename M = std::mutex>
277 using guarded [[deprecated(
"renamed to plain_guarded")]] = plain_guarded<T, M>;