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