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 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:
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) {
189 }
190
191 inline void writeLock(void) {
193 }
194
195 inline void tryReadLock(void) {
197 }
198
199 inline void tryWriteLock(void) {
201 }
202
203 inline void unlock(void) {
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) {
312 }
313
314 inline void leaveMutex(void) {
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) {
330 }
331
332 inline void post(void) {
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) {
387 }
388
389 inline bool wait(timeout_t timeout) {
390 return ucommon::TimedEvent::wait(timeout);
391 }
392
393 inline void signal(void) {
395 }
396
397 inline void reset(void) {
399 }
400
401 inline void set(timeout_t timeout = 0) {
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);
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) {
464 }
465
466 inline static void sleep(timeout_t msec = TIMEOUT_INF) {
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:
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
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
void unlock(void)
Unlock the conditional's supporting mutex.
Definition condition.h:107
void lock(void)
Lock the conditional's supporting mutex.
Definition condition.h:100
The conditional is a common base for other thread synchronizing classes.
Definition condition.h:228
void access(void)
Access mode shared thread scheduling.
void modify(void)
Exclusive mode write thread scheduling.
A portable counting semaphore class.
Definition condition.h:656
void release(void)
Release the semaphore after waiting for it.
void wait(void)
Wait until the semphore usage count is less than the thread limit.
A copy-on-write string class that operates by reference count.
Definition string.h:79
A generic and portable implementation of Read/Write locking.
Definition thread.h:84
void release(void)
Release the lock.
Event notification to manage scheduled realtime threads.
Definition thread.h:279
void reset(void)
Reset triggered conditional.
void wait(void)
A simple wait until triggered.
void signal(void)
Signal pending event.
Portable recursive exclusive lock.
Definition thread.h:370
static void yield(void)
Yield execution context of the current thread.
static void sleep(timeout_t timeout)
Sleep current thread for a specified time period.
A child thread object that may be joined by parent.
Definition thread.h:824
void set(void)
Set (update) the timer with current time.
The Mutex Counter is a counter variable which can safely be incremented or decremented by multiple th...
Definition thread.h:105
MutexCounter(int initial)
Create and optionally name a mutex protected counter with an initial value.
MutexCounter()
Create and optionally name a mutex protected counter.
The MutexLock class is used to protect a section of code so that at any given time only a single thre...
Definition thread.h:154
~MutexLock()
Release the mutex automatically.
Definition thread.h:174
MutexLock(Mutex &_mutex)
Acquire the mutex.
Definition thread.h:166
The ReadLock class is used to protect a section of code through a ThreadLock for "read" access to the...
Definition thread.h:229
ReadLock(ThreadLock &_tl)
Wait for read access.
Definition thread.h:241
~ReadLock()
Post the semaphore automatically.
Definition thread.h:248
The WriteLock class is used to protect a section of code through a ThreadLock for "write" access to t...
Definition thread.h:274
~WriteLock()
Post the semaphore automatically.
Definition thread.h:293
WriteLock(ThreadLock &_tl)
Wait for write access.
Definition thread.h:286
The SemaphoreLock class is used to protect a section of code through a semaphore so that only x insta...
Definition thread.h:357
~SemaphoreLock()
Post the semaphore automatically.
Definition thread.h:372
SemaphoreLock(Semaphore &_sem)
Wait for the semaphore.
Definition thread.h:365
This class is used to access non-reentrant date and time functions in the standard C library.
Definition thread.h:526
Timer ports are used to provide synchronized timing events when managed under a "service thread" such...
Definition thread.h:563
void sleepTimer(void)
Sleep until the current timer expires.
void setTimer(timeout_t timeout=0)
Set a new start time for the object based on when this call is made and optionally activate the timer...
timeout_t getElapsed(void) const
This is used to determine how much time has elapsed since a timer port setTimer benchmark time was in...
void decTimer(timeout_t timeout)
Adjust a timeout based on the current time reference value either from object creation or the last se...
void endTimer(void)
This is used to "disable" the service thread from expiring the timer object.
timeout_t getTimer(void) const
This is used by service threads to determine how much time remains before the timer expires based on ...
void incTimer(timeout_t timeout)
Set a timeout based on the current time reference value either from object creation or the last setTi...
TimerPort()
Create a timer, mark it as inactive, and set the initial "start" time to the creation time of the tim...
The buffer class represents an IPC service that is built upon a buffer of fixed capacity that can be ...
Definition thread.h:705
size_t getSize(void) const
Return the capacity of the buffer as specified at creation.
Definition thread.h:757
virtual bool isValid(void)
New virtual to test if buffer is a valid object.
virtual size_t onPeek(void *buf)=0
Invoke derived class buffer peeking method.
size_t wait(void *buf, timeout_t timeout=0)
Let one or more threads wait for an object to become available in the buffer.
virtual size_t onPost(void *buf)=0
Invoke derived class posting of object to buffer.
virtual size_t onWait(void *buf)=0
Invoke derived class object request from buffer.
size_t post(void *buf, timeout_t timeout=0)
Post an object into the buffer and enable a waiting thread to receive it.
size_t getUsed(void) const
Return the current capacity in use for the buffer.
Definition thread.h:767
static const size_t timeout
value to return when a timed operation returned with a timeout.
Definition thread.h:740
size_t peek(void *buf)
Peek at the current content (first object) in the buffer.
virtual ~Buffer()
In derived functions, may be used to free the actual memory used to hold buffered data.
Buffer(size_t capacity)
Create a buffer object of known capacity.
A buffer class that holds a known capacity of fixed sized objects defined during creation.
Definition thread.h:815
bool isValid(void)
New virtual to test if buffer is a valid object.
FixedBuffer(size_t capacity, size_t objsize)
Create a buffer of known capacity for objects of a specified size.
size_t onPost(void *buf)
Post an object of the appropriate size into the buffer.
virtual ~FixedBuffer()
Destroy the fixed buffer and free the memory used to store objects.
size_t onWait(void *buf)
Wait for and return a fixed object in the buffer.
FixedBuffer(const FixedBuffer &fb)
Create a copy of an existing fixed size buffer and duplicate it's contents.
size_t onPeek(void *buf)
Return the first object in the buffer.
Somewhat generic queue processing class to establish a producer consumer queue.
Definition thread.h:886
void setTimer(timeout_t timeout)
Set the queue timeout.
virtual void startQueue(void)
Start of dequeing.
virtual void onTimer(void)
A derivable method to call when the timout is expired.
virtual void stopQueue(void)
End of dequeing, we expect the queue is empty for now.
virtual ~ThreadQueue()
Destroy the queue.
ThreadQueue(const char *id, int pri, size_t stack=0)
Create instance of our queue and give it a process priority.
virtual void runQueue(void *data)=0
Virtual callback method to handle processing of a queued data items.
void post(const void *data, unsigned len)
Put some unspecified data into this queue.
Common C++ generic string class.