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
Common C++ generic string class.
MutexLock(Mutex &_mutex)
Acquire the mutex.
Definition: thread.h:166
The conditional is a common base for other thread synchronizing classes.
Definition: condition.h:227
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
A buffer class that holds a known capacity of fixed sized objects defined during creation.
Definition: thread.h:814
void wait(void)
Wait until the semphore usage count is less than the thread limit.
void set(void)
Set (update) the timer with current time.
void access(void)
Access mode shared thread scheduling.
Portable recursive exclusive lock.
Definition: thread.h:369
The buffer class represents an IPC service that is built upon a buffer of fixed capacity that can be ...
Definition: thread.h:703
void wait(void)
A simple wait until triggered.
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
Definition: address.h:59
static void yield(void)
Yield execution context of the current thread.
Event notification to manage scheduled realtime threads.
Definition: thread.h:278
void reset(void)
Reset triggered conditional.
~MutexLock()
Release the mutex automatically.
Definition: thread.h:174
~ReadLock()
Post the semaphore automatically.
Definition: thread.h:248
The ReadLock class is used to protect a section of code through a ThreadLock for "read" access to the...
Definition: thread.h:228
~WriteLock()
Post the semaphore automatically.
Definition: thread.h:293
A portable counting semaphore class.
Definition: condition.h:655
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
static const size_t timeout
value to return when a timed operation returned with a timeout.
Definition: thread.h:740
size_t getSize(void) const
Return the capacity of the buffer as specified at creation.
Definition: thread.h:757
Timer ports are used to provide synchronized timing events when managed under a "service thread" such...
Definition: thread.h:562
size_t post(void *buf, timeout_t timeout=0)
Post an object into the buffer and enable a waiting thread to receive it.
WriteLock(ThreadLock &_tl)
Wait for write access.
Definition: thread.h:286
void release(void)
Release the lock.
void signal(void)
Signal pending event.
This class is used to access non-reentrant date and time functions in the standard C library...
Definition: thread.h:525
The SemaphoreLock class is used to protect a section of code through a semaphore so that only x insta...
Definition: thread.h:356
ReadLock(ThreadLock &_tl)
Wait for read access.
Definition: thread.h:241
Common namespace for all ucommon objects.
Definition: access.h:47
size_t put(Buffer &b, void *o, timeout_t t=0)
Definition: thread.h:981
void unlock(void)
Unlock the conditional&#39;s supporting mutex.
Definition: condition.h:107
~SemaphoreLock()
Post the semaphore automatically.
Definition: thread.h:372
void lock(void)
Lock the conditional&#39;s supporting mutex.
Definition: condition.h:100
size_t getUsed(void) const
Return the current capacity in use for the buffer.
Definition: thread.h:767
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
size_t peek(Buffer &b, void *o)
Definition: thread.h:986
SemaphoreLock(Semaphore &_sem)
Wait for the semaphore.
Definition: thread.h:365
size_t peek(void *buf)
Peek at the current content (first object) in the buffer.
void modify(void)
Exclusive mode write thread scheduling.
void release(void)
Release the semaphore after waiting for it.
static void sleep(timeout_t timeout)
Sleep current thread for a specified time period.