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