18 #ifndef CSLIBGUARDED_COW_GUARDED_H
19 #define CSLIBGUARDED_COW_GUARDED_H
57 template <
typename T,
typename Mutex = std::mutex>
66 using shared_handle = std::shared_ptr<
const T>;
72 template <
typename... Us>
73 cow_guarded(Us &&... data);
106 template <
class Duration>
107 handle try_lock_for(
const Duration &duration);
122 template <
class TimePoint>
123 handle try_lock_until(
const TimePoint &timepoint);
129 shared_handle lock_shared()
const;
135 shared_handle try_lock_shared()
const;
141 template <
class Duration>
142 shared_handle try_lock_shared_for(
const Duration &duration)
const;
148 template <
class TimePoint>
149 shared_handle try_lock_shared_until(
const TimePoint &timepoint)
const;
159 deleter(std::unique_lock<Mutex> &&lock, cow_guarded &guarded)
160 : m_lock(std::move(lock)), m_guarded(&guarded), m_cancelled(
false)
167 if (m_lock.owns_lock()) {
172 void operator()(T *ptr) {
176 }
else if (ptr && m_guarded) {
177 std::shared_ptr<
const T> newPtr(ptr);
179 m_guarded->m_data.modify([newPtr](std::shared_ptr<
const T> &tmpPtr) { tmpPtr = newPtr; });
182 if (m_lock.owns_lock()) {
188 std::unique_lock<Mutex> m_lock;
189 cow_guarded *m_guarded;
197 class handle :
public std::unique_ptr<T, deleter>
200 using std::unique_ptr<T, deleter>::unique_ptr;
206 this->get_deleter().cancel();
212 mutable lr_guarded<std::shared_ptr<
const T>> m_data;
213 mutable Mutex m_writeMutex;
216 template <
typename T,
typename M>
217 template <
typename... Us>
218 cow_guarded<T, M>::cow_guarded(Us &&... data)
219 : m_data(std::make_shared<T>(std::forward<Us>(data)...))
223 template <
typename T,
typename M>
224 auto cow_guarded<T, M>::lock() -> handle
226 std::unique_lock<M> guard(m_writeMutex);
228 auto data(m_data.lock_shared());
229 std::unique_ptr<T> val(
new T(**data));
232 return handle(val.release(), deleter(std::move(guard), *
this));
235 template <
typename T,
typename M>
236 auto cow_guarded<T, M>::try_lock() -> handle
238 std::unique_lock<M> guard(m_writeMutex, std::try_to_lock);
240 if (!guard.owns_lock()) {
245 auto data(m_data.lock_shared());
247 std::unique_ptr<T> val(
new T(**data));
250 return handle(val.release(), deleter(std::move(guard), *
this));
253 template <
typename T,
typename M>
254 template <
typename Duration>
255 auto cow_guarded<T, M>::try_lock_for(
const Duration &duration) -> handle
257 std::unique_lock<M> guard(m_writeMutex, duration);
259 if (!guard.owns_lock()) {
264 auto data = m_data.lock_shared();
266 std::unique_ptr<T> val(
new T(**data));
269 return handle(val.release(), deleter(std::move(guard), *
this));
272 template <
typename T,
typename M>
273 template <
typename TimePoint>
274 auto cow_guarded<T, M>::try_lock_until(
const TimePoint &timepoint) -> handle
276 std::unique_lock<M> guard(m_writeMutex, timepoint);
278 if (! guard.owns_lock()) {
283 auto data(m_data.lock_shared());
285 std::unique_ptr<T> val(
new T(**data));
288 return handle(val.release(), deleter(std::move(guard), *
this));
291 template <
typename T,
typename M>
292 auto cow_guarded<T, M>::lock_shared()
const -> shared_handle
294 auto lock = m_data.lock_shared();
298 template <
typename T,
typename M>
299 auto cow_guarded<T, M>::try_lock_shared()
const -> shared_handle
301 shared_handle retval;
303 auto lock = m_data.try_lock_shared();
311 template <
typename T,
typename M>
312 template <
typename Duration>
313 auto cow_guarded<T, M>::try_lock_shared_for(
const Duration &duration)
const -> shared_handle
315 shared_handle retval;
317 auto lock = m_data.try_lock_shared_for(duration);
325 template <
typename T,
typename M>
326 template <
typename TimePoint>
327 auto cow_guarded<T, M>::try_lock_shared_until(
const TimePoint &timepoint)
const -> shared_handle
329 shared_handle retval;
331 auto lock = m_data.try_lock_shared_until(timepoint);