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>;