libcopp  2.2.0
lock_holder.h
Go to the documentation of this file.
1 
15 #pragma once
16 
17 // clang-format off
18 #include <libcopp/utils/config/stl_include_prefix.h> // NOLINT(build/include_order)
19 // clang-format on
20 #include <cstring>
21 // clang-format off
22 #include <libcopp/utils/config/stl_include_suffix.h> // NOLINT(build/include_order)
23 // clang-format on
24 
25 #include <libcopp/utils/config/libcopp_build_features.h>
26 
27 LIBCOPP_COPP_NAMESPACE_BEGIN
28 namespace util {
29 namespace lock {
30 namespace detail {
31 template <typename TLock>
32 struct LIBCOPP_COPP_API_HEAD_ONLY default_lock_action {
33  inline bool operator()(TLock &lock) const noexcept {
34  lock.lock();
35  return true;
36  }
37 };
38 
39 template <typename TLock>
40 struct LIBCOPP_COPP_API_HEAD_ONLY default_try_lock_action {
41  inline bool operator()(TLock &lock) const noexcept { return lock.try_lock(); }
42 };
43 
44 template <typename TLock>
45 struct LIBCOPP_COPP_API_HEAD_ONLY default_unlock_action {
46  inline void operator()(TLock &lock) const noexcept { lock.unlock(); }
47 };
48 
49 template <typename TLock>
50 struct LIBCOPP_COPP_API_HEAD_ONLY default_try_unlock_action {
51  inline bool operator()(TLock &lock) const noexcept { return lock.try_unlock(); }
52 };
53 
54 template <typename TLock>
55 struct LIBCOPP_COPP_API_HEAD_ONLY default_read_lock_action {
56  inline bool operator()(TLock &lock) const noexcept {
57  lock.read_lock();
58  return true;
59  }
60 };
61 
62 template <typename TLock>
63 struct LIBCOPP_COPP_API_HEAD_ONLY default_read_unlock_action {
64  inline void operator()(TLock &lock) const noexcept { lock.read_unlock(); }
65 };
66 
67 template <typename TLock>
68 struct LIBCOPP_COPP_API_HEAD_ONLY default_write_lock_action {
69  inline bool operator()(TLock &lock) const noexcept {
70  lock.write_lock();
71  return true;
72  }
73 };
74 
75 template <typename TLock>
76 struct LIBCOPP_COPP_API_HEAD_ONLY default_write_unlock_action {
77  inline void operator()(TLock &lock) const noexcept { lock.write_unlock(); }
78 };
79 } // namespace detail
80 
81 template <typename TLock, typename TLockAct = detail::default_lock_action<TLock>,
82  typename TUnlockAct = detail::default_unlock_action<TLock> >
83 class LIBCOPP_COPP_API_HEAD_ONLY lock_holder {
84  public:
85  using value_type = TLock;
86 
87  lock_holder(lock_holder &&other) : lock_flag_(other.lock_flag_) { other.lock_flag_ = nullptr; }
88 
89  inline lock_holder &operator=(lock_holder &&other) noexcept {
90  if (&other == this) {
91  return *this;
92  }
93 
94  if (lock_flag_ != other.lock_flag_) {
95  reset();
96  }
97 
98  lock_flag_ = other.lock_flag_;
99  return *this;
100  }
101 
102  inline lock_holder(TLock &lock) : lock_flag_(&lock) {
103  if (false == TLockAct()(lock)) {
104  lock_flag_ = nullptr;
105  }
106  }
107 
109  if (nullptr != lock_flag_) {
110  TUnlockAct()(*lock_flag_);
111  }
112  }
113 
114  inline bool is_available() const noexcept { return nullptr != lock_flag_; }
115 
116  inline void reset() noexcept {
117  if (nullptr != lock_flag_) {
118  value_type *value = lock_flag_;
119  lock_flag_ = nullptr;
120  TUnlockAct()(*value);
121  }
122  }
123 
124  private:
125  lock_holder(const lock_holder &) = delete;
126  lock_holder &operator=(const lock_holder &) = delete;
127 
128  private:
130 };
131 
132 template <typename TLock>
133 class LIBCOPP_COPP_API_HEAD_ONLY read_lock_holder
134  : public lock_holder<TLock, detail::default_read_lock_action<TLock>, detail::default_read_unlock_action<TLock> > {
135  public:
136  inline read_lock_holder(TLock &lock)
137  : lock_holder<TLock, detail::default_read_lock_action<TLock>, detail::default_read_unlock_action<TLock> >(lock) {}
138 };
139 
140 template <typename TLock>
141 class LIBCOPP_COPP_API_HEAD_ONLY write_lock_holder
142  : public lock_holder<TLock, detail::default_write_lock_action<TLock>, detail::default_write_unlock_action<TLock> > {
143  public:
144  inline write_lock_holder(TLock &lock)
145  : lock_holder<TLock, detail::default_write_lock_action<TLock>, detail::default_write_unlock_action<TLock> >(
146  lock) {}
147 };
148 } // namespace lock
149 } // namespace util
150 LIBCOPP_COPP_NAMESPACE_END
lock_holder(const lock_holder &)=delete
lock_holder(lock_holder &&other)
Definition: lock_holder.h:87
bool is_available() const noexcept
Definition: lock_holder.h:114
void reset() noexcept
Definition: lock_holder.h:116
lock_holder(TLock &lock)
Definition: lock_holder.h:102
lock_holder & operator=(lock_holder &&other) noexcept
Definition: lock_holder.h:89
value_type * lock_flag_
Definition: lock_holder.h:129
lock_holder & operator=(const lock_holder &)=delete
bool operator()(TLock &lock) const noexcept
Definition: lock_holder.h:33
bool operator()(TLock &lock) const noexcept
Definition: lock_holder.h:56
void operator()(TLock &lock) const noexcept
Definition: lock_holder.h:64
bool operator()(TLock &lock) const noexcept
Definition: lock_holder.h:41
bool operator()(TLock &lock) const noexcept
Definition: lock_holder.h:51
void operator()(TLock &lock) const noexcept
Definition: lock_holder.h:46
bool operator()(TLock &lock) const noexcept
Definition: lock_holder.h:69
void operator()(TLock &lock) const noexcept
Definition: lock_holder.h:77