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 
60 namespace ost {
61 
62 class __EXPORT Mutex : protected ucommon::RecursiveMutex
63 {
64 private:
65  __DELETE_COPY(Mutex);
66 
67 public:
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 
104 class __EXPORT MutexCounter : public Mutex
105 {
106 private:
107  __DELETE_COPY(MutexCounter);
108 
109 protected:
110  volatile int counter;
111 
112 public:
116  MutexCounter();
117 
124  MutexCounter(int initial);
125 
126  int operator++();
127  int operator--();
128 };
129 
153 class __EXPORT MutexLock
154 {
155 private:
156  Mutex& mutex;
157 
158  __DELETE_COPY(MutexLock);
159 
160 public:
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 
179 class __EXPORT ThreadLock : protected ucommon::RWLock
180 {
181 private:
182  __DELETE_COPY(ThreadLock);
183 
184 public:
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 
228 class __EXPORT ReadLock
229 {
230 private:
231  ThreadLock& tl;
232 
233  __DELETE_COPY(ReadLock);
234 
235 public:
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 
273 class __EXPORT WriteLock
274 {
275 private:
276  ThreadLock& tl;
277 
278  __DELETE_COPY(WriteLock);
279 
280 public:
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 
298 class __EXPORT Conditional : private ucommon::Conditional
299 {
300 private:
301  __DELETE_COPY(Conditional);
302 
303 public:
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 
319 class __EXPORT Semaphore : protected ucommon::Semaphore
320 {
321 public:
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 
356 class __EXPORT SemaphoreLock
357 {
358 private:
359  Semaphore& sem;
360 
361 public:
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 
377 class __EXPORT Event : private ucommon::TimedEvent
378 {
379 private:
380  __DELETE_COPY(Event);
381 
382 public:
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) {
402  ucommon::TimedEvent::set(timeout);
403  }
404 };
405 
406 class __EXPORT Thread : protected ucommon::JoinableThread
407 {
408 public:
412  typedef enum Throw {
413  throwNothing,
414  throwObject,
415  throwException
416  } Throw;
417 
418 private:
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 
429 public:
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 
525 class __EXPORT SysTime
526 {
527 private:
528  __DELETE_DEFAULTS(SysTime);
529 
530 public:
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 
562 class __EXPORT TimerPort
563 {
564 private:
565 #ifndef _MSWINDOWS_
566  struct timeval timer;
567 #else
568  DWORD timer;
569 #endif
570  bool active;
571 
572  __DELETE_COPY(TimerPort);
573 
574 public:
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_
654 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
655 #endif
656 
657 #if !defined(_MSWINDOWS_) || defined(_MSTHREADS_)
658 inline struct tm *localtime_r(const time_t *t, struct tm *b) {
659  return SysTime::getLocalTime(t, b);
660 }
661 
662 inline char *ctime_r(const time_t *t, char *buf) {
663  return ctime(t);
664 }
665 
666 inline struct tm *gmtime_r(const time_t *t, struct tm *b) {
667  return SysTime::getGMTTime(t, b);
668 }
669 
670 inline char *asctime_r(const struct tm *tm, char *b) {
671  return asctime(tm);
672 }
673 #endif
674 
675 inline Thread *getThread(void) {
676  return Thread::get();
677 }
678 
700 #ifdef _MSWINDOWS_
701 class __EXPORT Buffer : public Mutex
702 #else
703 class __EXPORT Buffer : public Conditional
704 #endif
705 {
706 private:
707 #ifdef _MSWINDOWS_
708  HANDLE sem_head, sem_tail;
709 #endif
710  size_t _size;
711  size_t _used;
712 
713 protected:
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 
735 public:
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 
814 class __EXPORT FixedBuffer : public Buffer
815 {
816 private:
817  char *buf, *head, *tail;
818  size_t objsize;
819 
820 protected:
826  size_t onPeek(void *buf) __OVERRIDE;
827 
833  size_t onWait(void *buf) __OVERRIDE;
834 
840  size_t onPost(void *buf) __OVERRIDE;
841 
842 public:
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 
885 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
886 {
887 private:
888  void run(void) __FINAL; // private run method
889 
890  __DELETE_COPY(ThreadQueue);
891 
892 protected:
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 
939 public:
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 
976 inline size_t get(Buffer &b, void *o, timeout_t t = 0) {
977  return b.wait(o, t);
978 }
979 
981 inline size_t put(Buffer &b, void *o, timeout_t t = 0) {
982  return b.post(o, t);
983 }
984 
986 inline size_t peek(Buffer &b, void *o) {
987  return b.peek(o);
988 }
989 
990 } // namespace ost
991 
992 #endif
A buffer class that holds a known capacity of fixed sized objects defined during creation.
Definition: thread.h:814
The conditional is a common base for other thread synchronizing classes.
Definition: condition.h:227
This class is used to access non-reentrant date and time functions in the standard C library.
Definition: thread.h:525
~MutexLock()
Release the mutex automatically.
Definition: thread.h:174
static const size_t timeout
value to return when a timed operation returned with a timeout.
Definition: thread.h:740
size_t put(Buffer &b, void *o, timeout_t t=0)
Definition: thread.h:981
~SemaphoreLock()
Post the semaphore automatically.
Definition: thread.h:372
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:356
MutexLock(Mutex &_mutex)
Acquire the mutex.
Definition: thread.h:166
A copy-on-write string class that operates by reference count.
Definition: string.h:78
The WriteLock class is used to protect a section of code through a ThreadLock for "write" access to t...
Definition: thread.h:273
The MutexLock class is used to protect a section of code so that at any given time only a single thre...
Definition: thread.h:153
size_t peek(void *buf)
Peek at the current content (first object) in the buffer.
void release(void)
Release the lock.
The buffer class represents an IPC service that is built upon a buffer of fixed capacity that can be ...
Definition: thread.h:703
void signal(void)
Signal pending event.
void lock(void)
Lock the conditional's supporting mutex.
Definition: condition.h:100
ReadLock(ThreadLock &_tl)
Wait for read access.
Definition: thread.h:241
void access(void)
Access mode shared thread scheduling.
~ReadLock()
Post the semaphore automatically.
Definition: thread.h:248
SemaphoreLock(Semaphore &_sem)
Wait for the semaphore.
Definition: thread.h:365
void wait(void)
Wait until the semphore usage count is less than the thread limit.
A generic and portable implementation of Read/Write locking.
Definition: thread.h:83
Somewhat generic queue processing class to establish a producer consumer queue.
Definition: thread.h:885
static void yield(void)
Yield execution context of the current thread.
Timer ports are used to provide synchronized timing events when managed under a "service thread" such...
Definition: thread.h:562
void set(void)
Set (update) the timer with current time.
void unlock(void)
Unlock the conditional's supporting mutex.
Definition: condition.h:107
size_t post(void *buf, timeout_t timeout=0)
Post an object into the buffer and enable a waiting thread to receive it.
void modify(void)
Exclusive mode write thread scheduling.
static void sleep(timeout_t timeout)
Sleep current thread for a specified time period.
Common C++ generic string class.
Portable recursive exclusive lock.
Definition: thread.h:369
size_t wait(void *buf, timeout_t timeout=0)
Let one or more threads wait for an object to become available in the buffer.
Common namespace for all ucommon objects.
Definition: access.h:47
void release(void)
Release the semaphore after waiting for it.
void reset(void)
Reset triggered conditional.
size_t getSize(void) const
Return the capacity of the buffer as specified at creation.
Definition: thread.h:757
void wait(void)
A simple wait until triggered.
size_t getUsed(void) const
Return the current capacity in use for the buffer.
Definition: thread.h:767
The ReadLock class is used to protect a section of code through a ThreadLock for "read" access to the...
Definition: thread.h:228
A child thread object that may be joined by parent.
Definition: thread.h:823
The Mutex Counter is a counter variable which can safely be incremented or decremented by multiple th...
Definition: thread.h:104
~WriteLock()
Post the semaphore automatically.
Definition: thread.h:293
size_t get(Buffer &b, void *o, timeout_t t=0)
Definition: thread.h:976
Event notification to manage scheduled realtime threads.
Definition: thread.h:278
size_t peek(Buffer &b, void *o)
Definition: thread.h:986
A portable counting semaphore class.
Definition: condition.h:655