CsLibGuarded  1.4.1
cs_ordered_guarded.h
1 /***********************************************************************
2 *
3 * Copyright (c) 2016-2024 Ansel Sermersheim
4 *
5 * This file is part of CsLibGuarded.
6 *
7 * CsLibGuarded is free software, released under the BSD 2-Clause license.
8 * For license details refer to LICENSE provided with this project.
9 *
10 * CsLibGuarded is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
13 *
14 * https://opensource.org/licenses/BSD-2-Clause
15 *
16 ***********************************************************************/
17 
18 #ifndef CSLIBGUARDED_ORDERED_GUARDED_H
19 #define CSLIBGUARDED_ORDERED_GUARDED_H
20 
21 #include <memory>
22 #include <mutex>
23 #include <type_traits>
24 #include <shared_mutex>
25 
26 namespace libguarded
27 {
28 
29 // 14 comment line(s) omitted
43 template <typename T, typename M = std::shared_timed_mutex>
44 class ordered_guarded
45 {
46  private:
47  class shared_deleter;
48 
49  public:
50  using shared_handle = std::unique_ptr<const T, shared_deleter>;
51 
52  // 4 comment line(s) omitted
56  template <typename... Us>
57  ordered_guarded(Us &&... data);
58 
59  template <typename Func>
60  decltype(auto) modify(Func &&func);
61 
62  template <typename Func>
63  [[nodiscard]] decltype(auto) read(Func &&func) const;
64 
65  [[nodiscard]] shared_handle lock_shared() const;
66  [[nodiscard]] shared_handle try_lock_shared() const;
67 
68  template <class Duration>
69  [[nodiscard]] shared_handle try_lock_shared_for(const Duration &duration) const;
70 
71  template <class TimePoint>
72  [[nodiscard]] shared_handle try_lock_shared_until(const TimePoint &timepoint) const;
73 
74  private:
75  class shared_deleter
76  {
77  public:
78  using pointer = const T *;
79 
80  shared_deleter() : m_deleter_mutex(nullptr) {}
81 
82  shared_deleter(M &mutex)
83  : m_deleter_mutex(&mutex)
84  {
85  }
86 
87  void operator()(const T *ptr) {
88  if (ptr && m_deleter_mutex) {
89  m_deleter_mutex->unlock_shared();
90  }
91  }
92 
93  private:
94  M *m_deleter_mutex;
95  };
96 
97  T m_obj;
98  mutable M m_mutex;
99 };
100 
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)...)
105 {
106 }
107 
108 template <typename T, typename M>
109 template <typename Func>
110 decltype(auto) ordered_guarded<T, M>::modify(Func &&func)
111 {
112  std::lock_guard<M> lock(m_mutex);
113 
114  return func(m_obj);
115 }
116 
117 template <typename T, typename M>
118 template <typename Func>
119 decltype(auto) ordered_guarded<T, M>::read(Func &&func) const
120 {
121  std::shared_lock<M> lock(m_mutex);
122 
123  return func(m_obj);
124 }
125 
126 template <typename T, typename M>
127 auto ordered_guarded<T, M>::lock_shared() const -> shared_handle
128 {
129  m_mutex.lock_shared();
130  return std::unique_ptr<const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
131 }
132 
133 template <typename T, typename M>
134 auto ordered_guarded<T, M>::try_lock_shared() const -> shared_handle
135 {
136  if (m_mutex.try_lock_shared()) {
137  return std::unique_ptr<const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
138  } else {
139  return std::unique_ptr<const T, shared_deleter>(nullptr, shared_deleter(m_mutex));
140  }
141 }
142 
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
146 {
147  if (m_mutex.try_lock_shared_for(duration)) {
148  return std::unique_ptr<const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
149  } else {
150  return std::unique_ptr<const T, shared_deleter>(nullptr, shared_deleter(m_mutex));
151  }
152 }
153 
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
157 {
158  if (m_mutex.try_lock_shared_until(timepoint)) {
159  return std::unique_ptr<const T, shared_deleter>(&m_obj, shared_deleter(m_mutex));
160  } else {
161  return std::unique_ptr<const T, shared_deleter>(nullptr, shared_deleter(m_mutex));
162  }
163 }
164 
165 } // namespace libguarded
166 
167 #endif