libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
rw_locking_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2011 by J.M.McGuiness, coder@hussar.me.uk
3 **
4 ** This library is free software; you can redistribute it and/or
5 ** modify it under the terms of the GNU Lesser General Public
6 ** License as published by the Free Software Foundation; either
7 ** version 2.1 of the License, or (at your option) any later version.
8 **
9 ** This library is distributed in the hope that it will be useful,
10 ** but WITHOUT ANY WARRANTY; without even the implied warranty of
11 ** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 ** Lesser General Public License for more details.
13 **
14 ** You should have received a copy of the GNU Lesser General Public
15 ** License along with this library; if not, write to the Free Software
16 ** Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
17 */
18 
19 namespace jmmcg { namespace LIBJMMCG_VER_NAMESPACE { namespace ppd { namespace lock { namespace rw {
20 
21  template<class L> inline constexpr
23  : rw_lk(l) {
24  }
25 
26  template<class L>
27  inline typename decaying_write_impl<L>::atomic_state_type
28  decaying_write_impl<L>::lock(const timeout_type) noexcept(false) {
29  return lock();
30  }
31 
32  template<class L>
33  inline typename decaying_write_impl<L>::atomic_state_type
34  decaying_write_impl<L>::unlock() noexcept(true) {
35  return rw_lk.unlock();
36  }
37 
38  template<class L>
39  inline void
40  decaying_write_impl<L>::decay() noexcept(true) {
41  rw_lk.decay();
42  }
43 
44  template<class T> inline constexpr
45  decaying_write_impl<locker<T> >::decaying_write_impl(atomic_t &l) noexcept(true)
46  : rw_lk(l), exclusive_w_lk(rw_lk.writer_lk), decayed(false) {
47  }
48 
49  template<class T>
50  inline typename decaying_write_impl<locker<T> >::atomic_state_type
51  decaying_write_impl<locker<T> >::lock() noexcept(false) {
52  exclusive_w_lk.lock();
53  const typename atomic_t::atomic_state_type ret=rw_lk.readers_free.lock();
54  assert(ret==lock_traits::atom_set);
55  assert(rw_lk.readers==0);
56  return ret;
57  }
58 
59  template<class T>
60  inline typename decaying_write_impl<locker<T> >::atomic_state_type
61  decaying_write_impl<locker<T> >::lock(const timeout_type) noexcept(false) {
62  return lock();
63  }
64 
65  template<class T>
66  inline typename decaying_write_impl<locker<T> >::atomic_state_type
67  decaying_write_impl<locker<T> >::unlock() noexcept(true) {
68  exclusive_w_lk.unlock();
69  if (!decayed) {
70  const typename atomic_t::atomic_state_type ret=rw_lk.readers_free.set();
71  assert(ret==lock_traits::atom_set);
72  return ret;
73  } else {
74  if ((--rw_lk.readers)==0) {
75  rw_lk.readers=typename atomic_t::atomic_counter_type(0);
76  assert(rw_lk.readers==0);
77  const typename atomic_t::atomic_state_type ret=rw_lk.readers_free.set();
78  assert(ret==lock_traits::atom_set);
79  return ret;
80  }
81  assert(rw_lk.readers>=0);
82  }
83  return lock_traits::atom_unset;
84  }
85 
86  template<class T>
87  inline void
88  decaying_write_impl<locker<T> >::decay() noexcept(true) {
89  if (!decayed) {
90  assert(rw_lk.readers==0);
91  ++rw_lk.readers;
92  decayed=true;
93  [[maybe_unused]] const typename atomic_t::atomic_state_type ret=exclusive_w_lk.unlock();
94  assert(ret==lock_traits::atom_unset);
95  }
96  }
97 
98  template<class T> inline
99  locker<T>::locker() noexcept(false)
100  : readers(), readers_free(lock_traits::atom_set) {
101  }
102 
103  template<class T> inline typename locker<T>::atomic_state_type
104  locker<T>::lock() noexcept(false) {
105  if ((readers++)==0) {
106  [[maybe_unused]] const typename locker::atomic_state_type ret=readers_free.lock();
107  assert(ret==lock_traits::atom_set);
108  }
109  return lock_traits::atom_set;
110  }
111 
112  template<class T> inline typename locker<T>::atomic_state_type
113  locker<T>::unlock() noexcept(true) {
114  if ((--readers)==0) {
116  assert(readers==0);
117  return readers_free.set();
118  }
119  if (readers<0) {
121  }
122  assert(readers>=0);
123  return lock_traits::atom_unset;
124  }
125 
126  template<class T> inline
127  locker<T>::read_lock_type::read_lock_type(atomic_t &l, const timeout_type) noexcept(false)
128  : lk(l) {
129  [[maybe_unused]] const typename atomic_t::atomic_state_type ret=lk.lock();
130  assert(ret==lock_traits::atom_set);
131  }
132 
133  template<class T> inline
134  locker<T>::read_lock_type::~read_lock_type() noexcept(true) {
135  assert(dynamic_cast<atomic_t *>(&lk));
136  lk.unlock();
137  }
138 
139  template<class T> inline
140  locker<T>::write_lock_type::write_lock_type(atomic_t &l, const timeout_type) noexcept(false)
141  : exclusive_w_lk(l.writer_lk, lock_traits::infinite_timeout()), rw_lk(l) {
142  [[maybe_unused]] const typename atomic_t::atomic_state_type ret=rw_lk.readers_free.lock();
143  assert(ret==lock_traits::atom_set);
144  assert(rw_lk.readers==0);
145  }
146 
147  template<class T> inline
148  locker<T>::write_lock_type::~write_lock_type() noexcept(true) {
149  assert(dynamic_cast<atomic_t *>(&rw_lk));
150  [[maybe_unused]] const typename atomic_t::atomic_state_type ret=rw_lk.readers_free.set();
151  assert(ret==lock_traits::atom_set);
152  }
153 
154  template<class T> inline
155  locker<T>::decaying_write_lock_type::decaying_write_lock_type(atomic_t &l, const timeout_type) noexcept(false)
156  : base_t(l) {
157  base_t::lock();
158  }
159 
160  template<class T> inline
161  locker<T>::decaying_write_lock_type::~decaying_write_lock_type() noexcept(true) {
162  base_t::unlock();
163  }
164 
165  template<class T> inline void
166  locker<T>::decaying_write_lock_type::decay() noexcept(true) {
167  base_t::decay();
168  }
169 
170 } } } } }