UCommon
thread.h
Go to the documentation of this file.
1// Copyright (C) 1999-2005 Open Source Telecom Corporation.
2// Copyright (C) 2006-2014 David Sugar, Tycho Softworks.
3// Copyright (C) 2015-2020 Cherokees of Idaho.
4//
5// This program is free software; you can redistribute it and/or modify
6// it under the terms of the GNU General Public License as published by
7// the Free Software Foundation; either version 3 of the License, or
8// (at your option) any later version.
9//
10// This program is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with this program. If not, see <http://www.gnu.org/licenses/>.
17//
18// As a special exception, you may use this file as part of a free software
19// library without restriction. Specifically, if other files instantiate
20// templates or use macros or inline functions from this file, or you compile
21// this file and link it with other files to produce an executable, this
22// file does not by itself cause the resulting executable to be covered by
23// the GNU General Public License. This exception does not however
24// invalidate any other reasons why the executable file might be covered by
25// the GNU General Public License.
26//
27// This exception applies only to the code released under the name GNU
28// Common C++. If you copy code from other releases into a copy of GNU
29// Common C++, as the General Public License permits, the exception does
30// not apply to the code that you add in this way. To avoid misleading
31// anyone as to the status of such modified files, you must delete
32// this exception notice from them.
33//
34// If you write modifications of your own for GNU Common C++, it is your choice
35// whether to permit this exception to apply to your modifications.
36// If you do not wish that, delete this exception notice.
37//
38
44#ifndef COMMONCPP_THREAD_H_
45#define COMMONCPP_THREAD_H_
46
47#ifndef COMMONCPP_CONFIG_H_
48#include <commoncpp/config.h>
49#endif
50
51#ifndef COMMONCPP_STRING_H_
52#include <commoncpp/string.h>
53#endif
54
55#define ENTER_CRITICAL enterMutex();
56#define LEAVE_CRITICAL leaveMutex();
57
58#include <time.h>
59
60namespace ost {
61
62class __EXPORT Mutex : protected ucommon::RecursiveMutex
63{
64private:
65 __DELETE_COPY(Mutex);
66
67public:
68 inline Mutex() : RecursiveMutex() {}
69
70 inline void enterMutex(void) {
71 RecursiveMutex::lock();
72 }
73
74 inline void leaveMutex(void) {
75 RecursiveMutex::release();
76 }
77
78 inline bool tryEnterMutex(void) {
79 return RecursiveMutex::lock(0l);
80 }
81
82 inline void enter(void) {
83 RecursiveMutex::lock();
84 }
85
86 inline void leave(void) {
87 RecursiveMutex::release();
88 }
89
90 inline bool test(void) {
91 return RecursiveMutex::lock(0l);
92 }
93};
94
104class __EXPORT MutexCounter : public Mutex
105{
106private:
107 __DELETE_COPY(MutexCounter);
108
109protected:
110 volatile int counter;
111
112public:
116 MutexCounter();
117
124 MutexCounter(int initial);
125
126 int operator++();
127 int operator--();
128};
129
153class __EXPORT MutexLock
154{
155private:
156 Mutex& mutex;
157
158 __DELETE_COPY(MutexLock);
159
160public:
166 inline MutexLock( Mutex& _mutex ) : mutex( _mutex ) {
167 mutex.enterMutex();
168 }
169
173 // this should be not-virtual
174 inline ~MutexLock() {
175 mutex.leaveMutex();
176 }
177};
178
179class __EXPORT ThreadLock : protected ucommon::RWLock
180{
181private:
182 __DELETE_COPY(ThreadLock);
183
184public:
185 inline ThreadLock() : ucommon::RWLock() {}
186
187 inline void readLock(void) {
188 ucommon::RWLock::access();
189 }
190
191 inline void writeLock(void) {
192 ucommon::RWLock::modify();
193 }
194
195 inline void tryReadLock(void) {
196 ucommon::RWLock::access(0);
197 }
198
199 inline void tryWriteLock(void) {
200 ucommon::RWLock::modify(0);
201 }
202
203 inline void unlock(void) {
204 ucommon::RWLock::release();
205 }
206};
207
228class __EXPORT ReadLock
229{
230private:
231 ThreadLock& tl;
232
233 __DELETE_COPY(ReadLock);
234
235public:
241 inline ReadLock( ThreadLock& _tl ) : tl( _tl ) {
242 tl.readLock();
243 }
247 // this should be not-virtual
248 inline ~ReadLock() {
249 tl.unlock();
250 }
251};
252
273class __EXPORT WriteLock
274{
275private:
276 ThreadLock& tl;
277
278 __DELETE_COPY(WriteLock);
279
280public:
286 inline WriteLock( ThreadLock& _tl ) : tl( _tl ) {
287 tl.writeLock();
288 }
292 // this should be not-virtual
293 inline ~WriteLock() {
294 tl.unlock();
295 }
296};
297
298class __EXPORT Conditional : private ucommon::Conditional
299{
300private:
301 __DELETE_COPY(Conditional);
302
303public:
304 inline Conditional() : ucommon::Conditional() {}
305
306 bool wait(timeout_t timeout, bool locked = false);
307
308 void signal(bool broadcast);
309
310 inline void enterMutex(void) {
311 ucommon::Conditional::lock();
312 }
313
314 inline void leaveMutex(void) {
315 ucommon::Conditional::unlock();
316 }
317};
318
319class __EXPORT Semaphore : protected ucommon::Semaphore
320{
321public:
322 inline Semaphore(unsigned size = 0) : ucommon::Semaphore(size) {}
323
324 inline bool wait(timeout_t timeout) {
325 return ucommon::Semaphore::wait(timeout);
326 }
327
328 inline void wait(void) {
329 ucommon::Semaphore::wait();
330 }
331
332 inline void post(void) {
333 ucommon::Semaphore::release();
334 }
335};
336
356class __EXPORT SemaphoreLock
357{
358private:
359 Semaphore& sem;
360
361public:
365 inline SemaphoreLock( Semaphore& _sem ) : sem( _sem ) {
366 sem.wait();
367 }
371 // this should be not-virtual
372 inline ~SemaphoreLock() {
373 sem.post();
374 }
375};
376
377class __EXPORT Event : private ucommon::TimedEvent
378{
379private:
380 __DELETE_COPY(Event);
381
382public:
383 inline Event() : ucommon::TimedEvent() {}
384
385 inline void wait(void) {
386 ucommon::TimedEvent::wait();
387 }
388
389 inline bool wait(timeout_t timeout) {
390 return ucommon::TimedEvent::wait(timeout);
391 }
392
393 inline void signal(void) {
394 ucommon::TimedEvent::signal();
395 }
396
397 inline void reset(void) {
398 ucommon::TimedEvent::reset();
399 }
400
401 inline void set(timeout_t timeout = 0) {
402 ucommon::TimedEvent::set(timeout);
403 }
404};
405
406class __EXPORT Thread : protected ucommon::JoinableThread
407{
408public:
412 typedef enum Throw {
413 throwNothing,
414 throwObject,
415 throwException
416 } Throw;
417
418private:
419 friend class Slog;
420
421 Throw exceptions;
422 bool detached, terminated;
423 Thread *parent;
424 size_t msgpos;
425 char msgbuf[128];
426
427 __DELETE_COPY(Thread);
428
429public:
430 Thread(int pri = 0, size_t stack = 0);
431
432 virtual ~Thread();
433
434 inline void map(void) {
435 JoinableThread::map();
436 }
437
438 virtual void initial(void);
439 virtual void notify(Thread *thread);
440 virtual void final(void);
441 virtual void run(void) __OVERRIDE = 0;
442
443 void terminate(void);
444 void finalize(void);
445
446 void detach(void);
447 void start(void);
448 void exit(void) __OVERRIDE;
449
450 inline void join(void) {
451 JoinableThread::join();
452 }
453
454 inline void sync(void) {
455 Thread::exit();
456 }
457
458 static inline Thread *get(void) {
459 return (Thread *)JoinableThread::get();
460 }
461
462 inline static void yield(void) {
463 ucommon::Thread::yield();
464 }
465
466 inline static void sleep(timeout_t msec = TIMEOUT_INF) {
467 ucommon::Thread::sleep(msec);
468 }
469
470 bool isRunning(void);
471
472 bool isThread(void);
473
479 static Throw getException(void);
480
486 static void setException(Throw mode);
487
491 inline pthread_t getId(void) const {
492 return tid;
493 }
494};
495
525class __EXPORT SysTime
526{
527private:
528 __DELETE_DEFAULTS(SysTime);
529
530public:
531 static time_t getTime(time_t *tloc = NULL);
532 static time_t time(time_t *tloc) {
533 return getTime(tloc);
534 }
535
536 static int getTimeOfDay(struct timeval *tp);
537 static int gettimeofday(struct timeval *tp, struct timezone *) {
538 return getTimeOfDay(tp);
539 }
540
541 static struct tm *getLocalTime(const time_t *clock, struct tm *result);
542 static struct tm *locatime(const time_t *clock, struct tm *result) {
543 return getLocalTime(clock, result);
544 }
545
546 static struct tm *getGMTTime(const time_t *clock, struct tm *result);
547 static struct tm *gmtime(const time_t *clock, struct tm *result) {
548 return getGMTTime(clock, result);
549 }
550};
551
562class __EXPORT TimerPort
563{
564private:
565#ifndef _MSWINDOWS_
566 struct timeval timer;
567#else
568 DWORD timer;
569#endif
570 bool active;
571
572 __DELETE_COPY(TimerPort);
573
574public:
581 TimerPort();
582
591 void setTimer(timeout_t timeout = 0);
592
602 void incTimer(timeout_t timeout);
603
613 void decTimer(timeout_t timeout);
614
619 void sleepTimer(void);
620
626 void endTimer(void);
627
639 timeout_t getTimer(void) const;
640
650 timeout_t getElapsed(void) const;
651};
652
653#ifndef _MSWINDOWS_
654struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
655#endif
656
657#if !defined(_MSWINDOWS_) || defined(_MSTHREADS_)
658inline struct tm *localtime_r(const time_t *t, struct tm *b) {
659 return SysTime::getLocalTime(t, b);
660}
661
662inline char *ctime_r(const time_t *t, char *buf) {
663 return ctime(t);
664}
665
666inline struct tm *gmtime_r(const time_t *t, struct tm *b) {
667 return SysTime::getGMTTime(t, b);
668}
669
670inline char *asctime_r(const struct tm *tm, char *b) {
671 return asctime(tm);
672}
673#endif
674
675inline Thread *getThread(void) {
676 return Thread::get();
677}
678
700#ifdef _MSWINDOWS_
701class __EXPORT Buffer : public Mutex
702#else
703class __EXPORT Buffer : public Conditional
704#endif
705{
706private:
707#ifdef _MSWINDOWS_
708 HANDLE sem_head, sem_tail;
709#endif
710 size_t _size;
711 size_t _used;
712
713protected:
719 virtual size_t onPeek(void *buf) = 0;
720
726 virtual size_t onWait(void *buf) = 0;
727
733 virtual size_t onPost(void *buf) = 0;
734
735public:
740 static const size_t timeout;
741
746 Buffer(size_t capacity);
751 virtual ~Buffer();
752
757 inline size_t getSize(void) const {
758 return _size;
759 }
760
767 inline size_t getUsed(void) const {
768 return _used;
769 }
770
780 size_t wait(void *buf, timeout_t timeout = 0);
781
790 size_t post(void *buf, timeout_t timeout = 0);
791
798 size_t peek(void *buf);
799
804 virtual bool isValid(void);
805};
806
814class __EXPORT FixedBuffer : public Buffer
815{
816private:
817 char *buf, *head, *tail;
818 size_t objsize;
819
820protected:
826 size_t onPeek(void *buf) __OVERRIDE;
827
833 size_t onWait(void *buf) __OVERRIDE;
834
840 size_t onPost(void *buf) __OVERRIDE;
841
842public:
850 FixedBuffer(size_t capacity, size_t objsize);
851
858 FixedBuffer(const FixedBuffer &fb);
859
863 virtual ~FixedBuffer();
864
865 FixedBuffer &operator=(const FixedBuffer &fb);
866
867 bool isValid(void) __OVERRIDE;
868};
869
885class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
886{
887private:
888 void run(void) __FINAL; // private run method
889
890 __DELETE_COPY(ThreadQueue);
891
892protected:
893 typedef struct _data {
894 struct _data *next;
895 unsigned len;
896 char data[1];
897 } data_t;
898
899 timeout_t timeout;
900 bool started;
901
902 data_t *first, *last; // head/tail of list
903
904 String name;
905
906 /*
907 * Overloading of final(). It demarks Semaphore to avoid deadlock.
908 */
909 virtual void final() __OVERRIDE;
910
915 virtual void startQueue(void);
916
922 virtual void stopQueue(void);
923
927 virtual void onTimer(void);
928
937 virtual void runQueue(void *data) = 0;
938
939public:
947 ThreadQueue(const char *id, int pri, size_t stack = 0);
948
952 virtual ~ThreadQueue();
953
961 void setTimer(timeout_t timeout);
962
971 void post(const void *data, unsigned len);
972};
973
974
976inline size_t get(Buffer &b, void *o, timeout_t t = 0) {
977 return b.wait(o, t);
978}
979
981inline size_t put(Buffer &b, void *o, timeout_t t = 0) {
982 return b.post(o, t);
983}
984
986inline size_t peek(Buffer &b, void *o) {
987 return b.peek(o);
988}
989
990} // namespace ost
991
992#endif
Common namespace for all ucommon objects.
Definition: access.h:47
Common C++ generic string class.