Qore Programming Language  1.12.0
qore_var_rwlock_priv.h
1 /* -*- mode: c++; indent-tabs-mode: nil -*- */
2 /*
3  qore_var_rwlock_priv.h
4 
5  internal read-write lock for variables
6 
7  Qore Programming Language
8 
9  Copyright (C) 2003 - 2022 Qore Technologies, s.r.o.
10 
11  Permission is hereby granted, free of charge, to any person obtaining a
12  copy of this software and associated documentation files (the "Software"),
13  to deal in the Software without restriction, including without limitation
14  the rights to use, copy, modify, merge, publish, distribute, sublicense,
15  and/or sell copies of the Software, and to permit persons to whom the
16  Software is furnished to do so, subject to the following conditions:
17 
18  The above copyright notice and this permission notice shall be included in
19  all copies or substantial portions of the Software.
20 
21  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
22  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
23  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
24  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
25  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
26  FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
27  DEALINGS IN THE SOFTWARE.
28 
29  Note that the Qore library is released under a choice of three open-source
30  licenses: MIT (as above), LGPL 2+, or GPL 2+; see README-LICENSE for more
31  information.
32 */
33 
34 #ifndef _QORE_VAR_RWLOCK_PRIV_H
35 #define _QORE_VAR_RWLOCK_PRIV_H
36 
37 class qore_var_rwlock_priv {
38 protected:
39  DLLLOCAL virtual void notifyIntern() {
40  }
41 
43  DLLLOCAL qore_var_rwlock_priv(const qore_var_rwlock_priv&);
45  DLLLOCAL qore_var_rwlock_priv& operator=(const qore_var_rwlock_priv&);
46 
47 public:
49  int write_tid,
50  readers,
51  read_waiting,
52  write_waiting;
53  QoreCondition write_cond,
54  read_cond;
55  bool has_notify;
56 
58  DLLLOCAL qore_var_rwlock_priv() : write_tid(-1), readers(0), read_waiting(0), write_waiting(0), has_notify(false) {
59  }
60 
62  DLLLOCAL virtual ~qore_var_rwlock_priv() {
63  }
64 
66  DLLLOCAL void wrlock() {
67  int tid = q_gettid();
68  AutoLocker al(l);
69  assert(tid != write_tid);
70 
71  while (readers || write_tid != -1) {
72  ++write_waiting;
73  write_cond.wait(l);
74  --write_waiting;
75  }
76 
77  write_tid = tid;
78  }
79 
81  DLLLOCAL int trywrlock() {
82  int tid = q_gettid();
83  AutoLocker al(l);
84  assert(tid != write_tid);
85  if (readers || write_tid != -1)
86  return -1;
87 
88  write_tid = tid;
89  return 0;
90  }
91 
93  DLLLOCAL void unlock() {
94  int tid = q_gettid();
95  AutoLocker al(l);
96  if (write_tid == tid) {
97  write_tid = -1;
98  if (has_notify)
99  notifyIntern();
100 
101  unlock_signal();
102  }
103  else {
104  assert(readers);
105  if (!--readers)
106  unlock_read_signal();
107  }
108  }
109 
111  DLLLOCAL void rdlock() {
112  AutoLocker al(l);
113  assert(write_tid != q_gettid());
114  while (write_tid != -1) {
115  ++read_waiting;
116  read_cond.wait(l);
117  --read_waiting;
118  }
119 
120  ++readers;
121  }
122 
124  DLLLOCAL int tryrdlock() {
125  AutoLocker al(l);
126  assert(write_tid != q_gettid());
127  if (write_tid != -1)
128  return -1;
129 
130  ++readers;
131  return 0;
132  }
133 
134  DLLLOCAL void unlock_signal() {
135  if (write_waiting)
136  write_cond.signal();
137  else if (read_waiting)
138  read_cond.broadcast();
139  }
140 
141  DLLLOCAL void unlock_read_signal() {
142  //assert(!read_waiting);
143  if (write_waiting)
144  write_cond.signal();
145  }
146 };
147 
148 class QoreAutoVarRWReadLocker {
149 private:
151  DLLLOCAL QoreAutoVarRWReadLocker(const QoreAutoVarRWReadLocker&);
152 
154  DLLLOCAL QoreAutoVarRWReadLocker& operator=(const QoreAutoVarRWReadLocker&);
155 
157  DLLLOCAL void *operator new(size_t);
158 
159 protected:
161  QoreVarRWLock *l;
162 
163 public:
165  DLLLOCAL QoreAutoVarRWReadLocker(QoreVarRWLock &n_l) : l(&n_l) {
166  l->rdlock();
167  }
168 
170  DLLLOCAL QoreAutoVarRWReadLocker(QoreVarRWLock *n_l) : l(n_l) {
171  l->rdlock();
172  }
173 
175  DLLLOCAL ~QoreAutoVarRWReadLocker() {
176  l->unlock();
177  }
178 };
179 
180 class QoreAutoVarRWWriteLocker {
181 private:
183  DLLLOCAL QoreAutoVarRWWriteLocker(const QoreAutoVarRWWriteLocker&);
184 
186  DLLLOCAL QoreAutoVarRWWriteLocker& operator=(const QoreAutoVarRWWriteLocker&);
187 
189  DLLLOCAL void *operator new(size_t);
190 
191 protected:
193  QoreVarRWLock *l;
194 
195 public:
197  DLLLOCAL QoreAutoVarRWWriteLocker(QoreVarRWLock &n_l) : l(&n_l) {
198  l->wrlock();
199  }
200 
202  DLLLOCAL QoreAutoVarRWWriteLocker(QoreVarRWLock *n_l) : l(n_l) {
203  l->wrlock();
204  }
205 
207  DLLLOCAL ~QoreAutoVarRWWriteLocker() {
208  l->unlock();
209  }
210 };
211 
212 class QoreSafeVarRWReadLocker {
213 private:
215  DLLLOCAL QoreSafeVarRWReadLocker(const QoreSafeVarRWReadLocker&);
216 
218  DLLLOCAL QoreSafeVarRWReadLocker& operator=(const QoreSafeVarRWReadLocker&);
219 
221  DLLLOCAL void *operator new(size_t);
222 
223 protected:
225  QoreVarRWLock *l;
226 
228  bool locked;
229 
230 public:
232  DLLLOCAL QoreSafeVarRWReadLocker(QoreVarRWLock &n_l) : l(&n_l) {
233  l->rdlock();
234  locked = true;
235  }
236 
238  DLLLOCAL QoreSafeVarRWReadLocker(QoreVarRWLock *n_l) : l(n_l) {
239  l->rdlock();
240  locked = true;
241  }
242 
244  DLLLOCAL ~QoreSafeVarRWReadLocker() {
245  if (locked)
246  l->unlock();
247  }
248 
250  DLLLOCAL void lock() {
251  assert(!locked);
252  l->rdlock();
253  locked = true;
254  }
255 
257  DLLLOCAL void unlock() {
258  assert(locked);
259  locked = false;
260  l->unlock();
261  }
262 
264  DLLLOCAL void stay_locked() {
265  assert(locked);
266  locked = false;
267  }
268 };
269 
270 class QoreSafeVarRWWriteLocker {
271 private:
273  DLLLOCAL QoreSafeVarRWWriteLocker(const QoreSafeVarRWWriteLocker&);
274 
276  DLLLOCAL QoreSafeVarRWWriteLocker& operator=(const QoreSafeVarRWWriteLocker&);
277 
279  DLLLOCAL void *operator new(size_t);
280 
281 protected:
283  QoreVarRWLock *l;
284 
286  bool locked;
287 
288 public:
290  DLLLOCAL QoreSafeVarRWWriteLocker(QoreVarRWLock &n_l) : l(&n_l) {
291  l->wrlock();
292  locked = true;
293  }
294 
296  DLLLOCAL QoreSafeVarRWWriteLocker(QoreVarRWLock *n_l) : l(n_l) {
297  l->wrlock();
298  locked = true;
299  }
300 
302  DLLLOCAL ~QoreSafeVarRWWriteLocker() {
303  if (locked)
304  l->unlock();
305  }
306 
308  DLLLOCAL void lock() {
309  assert(!locked);
310  l->wrlock();
311  locked = true;
312  }
313 
315  DLLLOCAL void unlock() {
316  assert(locked);
317  locked = false;
318  l->unlock();
319  }
320 
322  DLLLOCAL void stay_locked() {
323  assert(locked);
324  locked = false;
325  }
326 };
327 
328 class QoreOptionalVarRWWriteLocker {
329 protected:
330  QoreVarRWLock* l;
331 
332 public:
333  DLLLOCAL QoreOptionalVarRWWriteLocker(QoreVarRWLock* n_l) : l(n_l->trywrlock() ? 0 : n_l) {
334  }
335 
336  DLLLOCAL QoreOptionalVarRWWriteLocker(QoreVarRWLock& n_l) : l(n_l.trywrlock() ? 0 : &n_l) {
337  }
338 
339  DLLLOCAL ~QoreOptionalVarRWWriteLocker() {
340  if (l)
341  l->unlock();
342  }
343 
344  DLLLOCAL operator bool() const {
345  return (bool)l;
346  }
347 };
348 
349 class QoreOptionalVarRWReadLocker {
350 protected:
351  QoreVarRWLock* l;
352 
353 public:
354  DLLLOCAL QoreOptionalVarRWReadLocker(QoreVarRWLock* n_l) : l(n_l->tryrdlock() ? 0 : n_l) {
355  }
356 
357  DLLLOCAL QoreOptionalVarRWReadLocker(QoreVarRWLock& n_l) : l(n_l.tryrdlock() ? 0 : &n_l) {
358  }
359 
360  DLLLOCAL ~QoreOptionalVarRWReadLocker() {
361  if (l)
362  l->unlock();
363  }
364 
365  DLLLOCAL operator bool() const {
366  return (bool)l;
367  }
368 };
369 
370 #endif
provides a safe and exception-safe way to hold locks in Qore, only to be used on the stack,...
Definition: QoreThreadLock.h:136
a thread condition class implementing a wrapper for pthread_cond_t
Definition: QoreCondition.h:45
DLLEXPORT int wait(pthread_mutex_t *m)
blocks a thread on a mutex until the condition is signaled
DLLEXPORT int signal()
signals a single waiting thread to wake up
DLLEXPORT int broadcast()
singles all threads blocked on this condition to wake up
provides a mutually-exclusive thread lock
Definition: QoreThreadLock.h:49
DLLEXPORT int q_gettid() noexcept
returns the current TID number