libjmmcg  release_579_6_g8cffd
A C++ library containing an eclectic mix of useful, advanced components.
posix_locking_impl.hpp
Go to the documentation of this file.
1 /******************************************************************************
2 ** Copyright © 2004 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 pthreads {
20 
21  class condition_var::attr {
22  public:
23  explicit __stdcall attr(const int shared) noexcept(true) FORCE_INLINE {
24  [[maybe_unused]] const int ret1=pthread_condattr_init(&attr_);
25  assert(ret1==0);
26  [[maybe_unused]] const int ret2=pthread_condattr_setpshared(&attr_, shared);
27  assert(ret2==0);
28  }
29  attr(attr const &)=delete;
30  __stdcall ~attr() noexcept(true) FORCE_INLINE {
31  [[maybe_unused]] const int ret=pthread_condattr_destroy(&attr_);
32  assert(ret==0);
33  }
34 
35  operator pthread_condattr_t const *() const noexcept(true) FORCE_INLINE {
36  return &attr_;
37  }
38  operator pthread_condattr_t *() noexcept(true) FORCE_INLINE {
39  return &attr_;
40  }
41 
42  friend inline tostream &__fastcall FORCE_INLINE
43  operator<<(tostream &os, attr const &a) {
44  os<<static_cast<pthread_condattr_t const *>(a);
45  return os;
46  }
47 
48  private:
49  pthread_condattr_t attr_;
50  };
51 
52  inline
53  condition_var::condition_var(const int shared) noexcept(false) {
54  attr attrs(shared);
55  const atomic_state_type pth_err=static_cast<atomic_state_type>(pthread_cond_init(&cond_var, static_cast<const pthread_condattr_t *>(attrs)));
56  if (pth_err!=lock_traits::atom_set) {
57  info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(*this), info::function::argument(_T("const int shared"), tostring(shared)));
58  fun.add_args(
59  info::function::argument(_T("attr"), tostring(attrs)),
60  info::function::argument(_T("Return code"), tostring(pth_err))
61  );
62  throw exception_type(_T("Could not initialise condition variable."), std::move(fun), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
63  }
64  }
65 
66  inline
67  condition_var::~condition_var() noexcept(true) {
68  [[maybe_unused]] const atomic_state_type pth_err=static_cast<atomic_state_type>(pthread_cond_destroy(&cond_var));
69  assert(pth_err==lock_traits::atom_set);
70  }
71 
72  class anon_mutex::attr {
73  public:
74  __stdcall attr(const int shared, const int err_chk) noexcept(true) FORCE_INLINE {
75  [[maybe_unused]] const int ret1=pthread_mutexattr_init(&attr_);
76  assert(ret1==0);
77  [[maybe_unused]] const int ret2=pthread_mutexattr_setpshared(&attr_,shared);
78  assert(ret2==0);
79  [[maybe_unused]] const int ret3=pthread_mutexattr_settype(&attr_,err_chk);
80  assert(ret3==0);
81  }
82  attr(attr const &)=delete;
83  __stdcall ~attr() noexcept(true) FORCE_INLINE {
84  [[maybe_unused]] const int ret=pthread_mutexattr_destroy(&attr_);
85  assert(ret==0);
86  }
87 
88  operator pthread_mutexattr_t const *() const noexcept(true) FORCE_INLINE {
89  return &attr_;
90  }
91  operator pthread_mutexattr_t *() noexcept(true) FORCE_INLINE {
92  return &attr_;
93  }
94 
95  friend inline tostream &__fastcall FORCE_INLINE
96  operator<<(tostream &os, attr const &a) noexcept(false) {
97  os<<static_cast<pthread_mutexattr_t const *>(a);
98  return os;
99  }
100 
101  private:
102  pthread_mutexattr_t attr_;
103  };
104 
105  inline
106  anon_mutex::anon_mutex() noexcept(false) {
107  attr attrs(PTHREAD_PROCESS_PRIVATE, PTHREAD_MUTEX_ERRORCHECK);
108  const atomic_state_type pth_err=static_cast<atomic_state_type>(pthread_mutex_init(&mutex, static_cast<pthread_mutexattr_t *>(attrs)));
109  if (pth_err!=lock_traits::atom_set) {
110  info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(*this), info::function::argument(_T("attr"), tostring(attrs)));
111  fun.add_arg(info::function::argument(_T("Return code"), tostring(pth_err)));
112  throw exception_type(_T("Could not initialise the mutex."), std::move(fun), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
113  }
114  }
115 
116  inline
117  anon_mutex::~anon_mutex() noexcept(true) {
118  [[maybe_unused]] const atomic_state_type pth_err=static_cast<atomic_state_type>(pthread_mutex_destroy(&mutex));
119  assert(pth_err==lock_traits::atom_set);
120  }
121 
122  inline
123  anon_mutex::operator api_mutex_type *() noexcept(true) {
124  return &mutex;
125  }
126 
128  anon_mutex::lock() noexcept(true) {
129  return static_cast<atomic_state_type>(pthread_mutex_lock(&mutex));
130  }
131 
133  anon_mutex::lock(const timeout_type timeout) noexcept(true) {
134  if (timeout==lock_traits::infinite_timeout()) {
135  return lock();
136  } else {
137  return static_cast<atomic_state_type>(pthread_mutex_trylock(&mutex));
138  }
139  }
140 
142  anon_mutex::unlock() noexcept(true) {
143  const atomic_state_type ret=static_cast<atomic_state_type>(pthread_mutex_unlock(&mutex));
144  return ret ? static_cast<atomic_state_type>(ret) : lock_traits::atom_unset;
145  }
146 
147  inline void
148  anon_mutex::decay() noexcept(true) {
149  }
150 
151  inline
152  anon_mutex::anon_mutex(const int shared, const int err_chk) noexcept(false) {
153  attr attrs(shared, err_chk);
154  const atomic_state_type pth_err=static_cast<atomic_state_type>(pthread_mutex_init(&mutex, static_cast<pthread_mutexattr_t *>(attrs)));
155  if (pth_err!=lock_traits::atom_set) {
156  info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(*this), info::function::argument(_T("const int shared"), tostring(shared)));
157  fun.add_args(
158  info::function::argument(_T("const int err_chk"), tostring(err_chk)),
159  info::function::argument(_T("attr"), tostring(attrs)),
160  info::function::argument(_T("Return code"), tostring(pth_err))
161  );
162  throw exception_type(_T("Could not initialise mutex."), std::move(fun), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
163  }
164  }
165 
166  inline
167  anon_semaphore::anon_semaphore(const atomic_state_type state) noexcept(false) {
168  const atomic_state_type err=static_cast<atomic_state_type>(sem_init(&sem, 0, state==lock_traits::atom_set));
169  if (err!=lock_traits::atom_set) {
170  info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(*this), info::function::argument(_T("const atomic_state_type state"), tostring(state)));
171  fun.add_arg(info::function::argument(_T("Return code"), tostring(err)));
172  throw exception_type(_T("Could not initialise anonymous semaphore."), std::move(fun), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
173  }
174  }
175 
176  inline
177  anon_semaphore::anon_semaphore(const atomic_state_type state, int shared) noexcept(false) {
178  const atomic_state_type err=static_cast<atomic_state_type>(sem_init(&sem, shared, state==lock_traits::atom_set));
179  if (err!=lock_traits::atom_set) {
180  info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(*this), info::function::argument(_T("const atomic_state_type state"), tostring(state)));
181  fun.add_args(
182  info::function::argument(_T("atomic_state_type state"), tostring(state)),
183  info::function::argument(_T("int shared"), tostring(shared)),
184  info::function::argument(_T("Return code"), tostring(err))
185  );
186  throw exception_type(_T("Could not initialise anonymous semaphore."), std::move(fun), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
187  }
188  }
189 
190  inline
191  anon_semaphore::~anon_semaphore() noexcept(true) {
192  [[maybe_unused]] const atomic_state_type err=static_cast<atomic_state_type>(sem_destroy(&sem));
193  assert(err==lock_traits::atom_set);
194  }
195 
196  inline
197  anon_semaphore::operator api_event_type *() noexcept(true) {
198  return static_cast<api_event_type *>(&sem);
199  }
200 
202  anon_semaphore::set() noexcept(true) {
203  return static_cast<atomic_state_type>(sem_post(&sem));
204  }
205 
207  anon_semaphore::unlock() noexcept(true) {
208  return static_cast<atomic_state_type>(sem_trywait(&sem));
209  }
210 
212  anon_semaphore::reset() noexcept(true) {
213  return unlock();
214  }
215 
217  anon_semaphore::try_lock() noexcept(true) {
218  if (!sem_trywait(&sem)) {
219  return lock_traits::atom_set;
220  } else {
221  return lock_traits::atom_unset;
222  }
223  }
224 
226  anon_semaphore::lock() noexcept(false) {
227  if (!sem_wait(&sem)) {
228  return lock_traits::atom_set;
229  } else {
230  return lock_traits::atom_abandoned;
231  }
232  }
233 
234  inline void
235  anon_semaphore::clear() noexcept(true) {
236  while (try_lock()==lock_traits::atom_set);
237  }
238 
239  inline anon_semaphore::count_type
240  anon_semaphore::count() const noexcept(false) {
241  count_type val=0;
242  const atomic_state_type err=static_cast<atomic_state_type>(sem_getvalue(&sem, &val));
243  if (err!=lock_traits::atom_set) {
244  info::function fun(__LINE__, __PRETTY_FUNCTION__, typeid(&anon_semaphore::count), info::function::argument(_T("count_type val"), tostring(val)));
245  fun.add_arg(info::function::argument(_T("Return code"), tostring(err)));
246  throw exception_type(_T("Could not get the count from the semaphore object."), std::move(fun), JMMCG_REVISION_HDR(_T(LIBJMMCG_VERSION_NUMBER)));
247  }
248  return val;
249  }
250 
251  inline
252  nonrecursive_anon_mutex::nonrecursive_anon_mutex() noexcept(noexcept(anon_semaphore(lock_traits::atom_set))) {
253  assert(event_.count()==1);
254  }
255 
256  inline
257  nonrecursive_anon_mutex::~nonrecursive_anon_mutex() noexcept(true) {
258  event_.clear();
259  }
260 
261  inline nonrecursive_anon_mutex::atomic_state_type
262  nonrecursive_anon_mutex::lock(const timeout_type timeout) noexcept(noexcept(event_.lock(timeout))) {
263  const atomic_state_type ret=event_.lock(timeout);
264  assert(event_.count()>=0);
265  return ret;
266  }
267 
268  inline nonrecursive_anon_mutex::atomic_state_type
269  nonrecursive_anon_mutex::lock() noexcept(noexcept(event_.lock())) {
270  const atomic_state_type ret=event_.lock();
271  assert(event_.count()>=0);
272  return ret;
273  }
274 
275  inline nonrecursive_anon_mutex::atomic_state_type
276  nonrecursive_anon_mutex::unlock() noexcept(noexcept(event_.set())) {
277  assert(event_.count()>=0);
278  const atomic_state_type ret=event_.set();
279  assert(event_.count()>=0);
280  return ret;
281  }
282 
283  inline void
284  nonrecursive_anon_mutex::decay() noexcept(true) {
285  }
286 
287 } } } }