UCommon
condition.h
Go to the documentation of this file.
1// Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
2// Copyright (C) 2015-2020 Cherokees of Idaho.
3//
4// This file is part of GNU uCommon C++.
5//
6// GNU uCommon C++ is free software: you can redistribute it and/or modify
7// it under the terms of the GNU Lesser General Public License as published
8// by the Free Software Foundation, either version 3 of the License, or
9// (at your option) any later version.
10//
11// GNU uCommon C++ is distributed in the hope that it will be useful,
12// but WITHOUT ANY WARRANTY; without even the implied warranty of
13// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14// GNU Lesser General Public License for more details.
15//
16// You should have received a copy of the GNU Lesser General Public License
17// along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
18
34#ifndef _UCOMMON_CONDITION_H_
35#define _UCOMMON_CONDITION_H_
36
37#ifndef _UCOMMON_CPR_H_
38#include <ucommon/cpr.h>
39#endif
40
41#ifndef _UCOMMON_ACCESS_H_
42#include <ucommon/access.h>
43#endif
44
45#ifndef _UCOMMON_TIMERS_H_
46#include <ucommon/timers.h>
47#endif
48
49#ifndef _UCOMMON_MEMORY_H_
50#include <ucommon/memory.h>
51#endif
52
53namespace ucommon {
54
61class __EXPORT ConditionMutex
62{
63private:
64 friend class ConditionVar;
65 friend class autolock;
66
67 __DELETE_COPY(ConditionMutex);
68
69protected:
70#if defined(_MSTHREADS_)
71 mutable CRITICAL_SECTION mutex;
72#else
73 mutable pthread_mutex_t mutex;
74#endif
75
76public:
80 ConditionMutex();
81
85 ~ConditionMutex();
86
87#ifdef _MSTHREADS_
88 inline void lock(void) {
89 EnterCriticalSection(&mutex);
90 }
91
92 inline void unlock(void) {
93 LeaveCriticalSection(&mutex);
94 }
95
96#else
100 inline void lock(void) {
101 pthread_mutex_lock(&mutex);
102 }
103
107 inline void unlock(void) {
108 pthread_mutex_unlock(&mutex);
109 }
110#endif
111
112 class __EXPORT autolock
113 {
114 private:
115#ifdef _MSTHREADS_
116 CRITICAL_SECTION *mutex;
117#else
118 pthread_mutex_t *mutex;
119#endif
120 __DELETE_COPY(autolock);
121
122 public:
123 inline autolock(const ConditionMutex* object) {
124 mutex = &object->mutex;
125#ifdef _MSTHREADS_
126 EnterCriticalSection(mutex);
127#else
128 pthread_mutex_lock(mutex);
129#endif
130 }
131
132 inline ~autolock() {
133#ifdef _MSTHREADS_
134 LeaveCriticalSection(mutex);
135#else
136 pthread_mutex_unlock(mutex);
137#endif
138 }
139 };
140};
141
148class __EXPORT ConditionVar
149{
150private:
151 __DELETE_DEFAULTS(ConditionVar);
152
153protected:
154 friend class ConditionList;
155
156#if defined(_MSTHREADS_)
157 mutable CONDITION_VARIABLE cond;
158#else
159 mutable pthread_cond_t cond;
160#endif
161 ConditionMutex *shared;
162
163public:
167 ConditionVar(ConditionMutex *mutex);
168
172 ~ConditionVar();
173
179 bool wait(timeout_t timeout);
180
186 bool wait(struct timespec *timeout);
187
188#ifdef _MSTHREADS_
189 void wait(void);
190 void signal(void);
191 void broadcast(void);
192
193#else
197 inline void wait(void) {
198 pthread_cond_wait(&cond, &shared->mutex);
199 }
200
204 inline void signal(void) {
205 pthread_cond_signal(&cond);
206 }
207
211 inline void broadcast(void) {
212 pthread_cond_broadcast(&cond);
213 }
214#endif
215};
216
227class __EXPORT Conditional : protected ConditionMutex
228{
229private:
230 __DELETE_COPY(Conditional);
231
232protected:
233 friend class ConditionalAccess;
234 friend class ConditionVar;
235
236#if defined(_MSTHREADS_)
237 mutable CONDITION_VARIABLE cond;
238#else
239#ifndef __PTH__
240 class __LOCAL attribute
241 {
242 public:
243 pthread_condattr_t attr;
244 attribute();
245 };
246
247 __LOCAL static attribute attr;
248#endif
249
250 mutable pthread_cond_t cond;
251#endif
252
253 friend class TimedEvent;
254
260 bool wait(timeout_t timeout);
261
267 bool wait(struct timespec *timeout);
268
269#ifdef _MSTHREADS_
270 void wait(void);
271 void signal(void);
272 void broadcast(void);
273
274#else
278 inline void wait(void) {
279 pthread_cond_wait(&cond, &mutex);
280 }
281
285 inline void signal(void) {
286 pthread_cond_signal(&cond);
287 }
288
292 inline void broadcast(void) {
293 pthread_cond_broadcast(&cond);
294 }
295#endif
296
300 Conditional();
301
305 ~Conditional();
306
307 friend class autolock;
308
309public:
310#if !defined(_MSTHREADS_) && !defined(__PTH__)
316 static inline pthread_condattr_t *initializer(void) {
317 return &attr.attr;
318 }
319#endif
320
327 static void set(struct timespec *hires, timeout_t timeout);
328};
329
337class __EXPORT ConditionalAccess : private Conditional
338{
339private:
340 __DELETE_COPY(ConditionalAccess);
341
342protected:
343#if defined _MSTHREADS_
344 CONDITION_VARIABLE bcast;
345#else
346 mutable pthread_cond_t bcast;
347#endif
348
349 static unsigned max_sharing;
350
351 unsigned pending, waiting, sharing;
352
358 bool waitSignal(timeout_t timeout);
359
365 bool waitBroadcast(timeout_t timeout);
366
367
373 bool waitSignal(struct timespec *timeout);
374
380 bool waitBroadcast(struct timespec *timeout);
381
388 inline static void set(struct timespec *hires, timeout_t timeout) {
389 Conditional::set(hires, timeout);
390 }
391
392
393#ifdef _MSTHREADS_
394 inline void lock(void) {
395 EnterCriticalSection(&mutex);
396 }
397
398 inline void unlock(void) {
399 LeaveCriticalSection(&mutex);
400 }
401
402 void waitSignal(void);
403
404 void waitBroadcast(void);
405
406 inline void signal(void) {
407 Conditional::signal();
408 }
409
410 inline void broadcast(void) {
411 Conditional::broadcast();
412 }
413
414#else
418 inline void lock(void) {
419 pthread_mutex_lock(&mutex);
420 }
421
425 inline void unlock(void) {
426 pthread_mutex_unlock(&mutex);
427 }
428
432 inline void waitSignal(void) {
433 pthread_cond_wait(&cond, &mutex);
434 }
435
439 inline void waitBroadcast(void) {
440 pthread_cond_wait(&bcast, &mutex);
441 }
442
443
447 inline void signal(void) {
448 pthread_cond_signal(&cond);
449 }
450
454 inline void broadcast(void) {
455 pthread_cond_broadcast(&bcast);
456 }
457#endif
458public:
462 ConditionalAccess();
463
467 ~ConditionalAccess();
468
472 void access(void);
473
477 void modify(void);
478
482 void release(void);
483
487 void commit(void);
488
495 void limit_sharing(unsigned max);
496};
497
508class __EXPORT ConditionalLock : protected ConditionalAccess, public __PROTOCOL SharedProtocol
509{
510private:
511 __DELETE_COPY(ConditionalLock);
512
513protected:
514 class Context : public LinkedObject
515 {
516 private:
517 __DELETE_COPY(Context);
518
519 public:
520 inline Context(LinkedObject **root) : LinkedObject(root) {}
521
522 pthread_t thread;
523 unsigned count;
524 };
525
526 LinkedObject *contexts;
527
528 virtual void _share(void) __OVERRIDE;
529 virtual void _unshare(void) __OVERRIDE;
530
531 Context *getContext(void);
532
533public:
537 ConditionalLock();
538
542 ~ConditionalLock();
543
547 void modify(void);
548
552 void commit(void);
553
557 void access(void);
558
562 void release(void);
563
568 virtual void exclusive(void) __OVERRIDE;
569
573 virtual void share(void) __OVERRIDE;
574};
575
588class __EXPORT Barrier : private Conditional
589{
590private:
591 unsigned count;
592 unsigned waits;
593
594 __DELETE_DEFAULTS(Barrier);
595
596public:
601 Barrier(unsigned count);
602
606 ~Barrier();
607
613 void set(unsigned count);
614
618 void inc(void);
619
623 void dec(void);
624
629 unsigned operator++(void);
630
631 unsigned operator--(void);
632
636 void wait(void);
637
644 bool wait(timeout_t timeout);
645};
646
655class __EXPORT Semaphore : public __PROTOCOL SharedProtocol, protected Conditional
656{
657protected:
658 unsigned count, waits, used;
659
660 virtual void _share(void) __OVERRIDE;
661 virtual void _unshare(void) __OVERRIDE;
662
663 __DELETE_COPY(Semaphore);
664
665public:
666 typedef autoshared<Semaphore> autosync;
667
672 Semaphore(unsigned count = 0);
673
679 Semaphore(unsigned count, unsigned avail);
680
685 void wait(void);
686
694 bool wait(timeout_t timeout);
695
700 void set(unsigned count);
701
705 void release(void);
706
710 inline void operator++(void) {
711 wait();
712 }
713
717 inline void operator--(void) {
718 release();
719 }
720};
721
725typedef ConditionalLock condlock_t;
726
730typedef ConditionalAccess accesslock_t;
731
735typedef Semaphore semaphore_t;
736
740typedef Barrier barrier_t;
741
742} // namespace ucommon
743
744#endif
Private heaps, pools, and associations.
Realtime timers and timer queues.
Runtime functions.
Locking protocol classes for member function automatic operations.
Common namespace for all ucommon objects.
Definition access.h:47
ConditionalAccess accesslock_t
Convenience type for scheduling access.
Definition condition.h:730
Semaphore semaphore_t
Convenience type for using counting semaphores.
Definition condition.h:735
class __attribute__((visibility("default"))) Conditional class __attribute__((visibility("default"))) ConditionalAccess class __attribute__((visibility("default"))) ConditionalLock class __attribute__((visibility("default"))) Barrier class __attribute__((visibility("default"))) Semaphore typedef ConditionalLock condlock_t
The conditional is a common base for other thread synchronizing classes.
Definition condition.h:655
Barrier barrier_t
Convenience type for using thread barriers.
Definition condition.h:740