18 #ifndef CSLIBGUARDED_ORDERED_GUARDED_H 
   19 #define CSLIBGUARDED_ORDERED_GUARDED_H 
   23 #include <type_traits> 
   24 #include <shared_mutex> 
   43 template <
typename T, 
typename M = std::shared_timed_mutex>
 
   50       using shared_handle = std::unique_ptr<
const T, shared_deleter>;
 
   56       template <
typename... Us>
 
   57       ordered_guarded(Us &&... data);
 
   59       template <
typename Func>
 
   60       decltype(
auto) modify(Func &&func);
 
   62       template <
typename Func>
 
   63       [[nodiscard]] 
decltype(
auto) read(Func &&func) 
const;
 
   65       [[nodiscard]] shared_handle lock_shared() 
const;
 
   66       [[nodiscard]] shared_handle try_lock_shared() 
const;
 
   68       template <
class Duration>
 
   69       [[nodiscard]] shared_handle try_lock_shared_for(
const Duration &duration) 
const;
 
   71       template <
class TimePoint>
 
   72       [[nodiscard]] shared_handle try_lock_shared_until(
const TimePoint &timepoint) 
const;
 
   78             using pointer = 
const T *;
 
   80             shared_deleter() : m_deleter_mutex(
nullptr) {}
 
   82             shared_deleter(M &mutex)
 
   83                : m_deleter_mutex(&mutex)
 
   87             void operator()(
const T *ptr) {
 
   88                if (ptr && m_deleter_mutex) {
 
   89                   m_deleter_mutex->unlock_shared();
 
  101 template <
typename T, 
typename M>
 
  102 template <
typename... Us>
 
  103 ordered_guarded<T, M>::ordered_guarded(Us &&... data)
 
  104    : m_obj(std::forward<Us>(data)...)
 
  108 template <
typename T, 
typename M>
 
  109 template <
typename Func>
 
  110 decltype(
auto) ordered_guarded<T, M>::modify(Func &&func)
 
  112    std::lock_guard<M> lock(m_mutex);
 
  117 template <
typename T, 
typename M>
 
  118 template <
typename Func>
 
  119 decltype(
auto) ordered_guarded<T, M>::read(Func &&func) 
const 
  121    std::shared_lock<M> lock(m_mutex);
 
  126 template <
typename T, 
typename M>
 
  127 auto ordered_guarded<T, M>::lock_shared() 
const -> shared_handle
 
  129    m_mutex.lock_shared();
 
  130    return std::unique_ptr<
const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
 
  133 template <
typename T, 
typename M>
 
  134 auto ordered_guarded<T, M>::try_lock_shared() 
const -> shared_handle
 
  136    if (m_mutex.try_lock_shared()) {
 
  137       return std::unique_ptr<
const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
 
  139       return std::unique_ptr<
const T, shared_deleter>(
nullptr, shared_deleter(m_mutex));
 
  143 template <
typename T, 
typename M>
 
  144 template <
typename Duration>
 
  145 auto ordered_guarded<T, M>::try_lock_shared_for(
const Duration &duration) 
const -> shared_handle
 
  147    if (m_mutex.try_lock_shared_for(duration)) {
 
  148       return std::unique_ptr<
const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
 
  150       return std::unique_ptr<
const T, shared_deleter>(
nullptr, shared_deleter(m_mutex));
 
  154 template <
typename T, 
typename M>
 
  155 template <
typename TimePoint>
 
  156 auto ordered_guarded<T, M>::try_lock_shared_until(
const TimePoint &timepoint) 
const -> shared_handle
 
  158    if (m_mutex.try_lock_shared_until(timepoint)) {
 
  159       return std::unique_ptr<
const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
 
  161       return std::unique_ptr<
const T, shared_deleter>(
nullptr, shared_deleter(m_mutex));