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 //
4 // This program is free software; you can redistribute it and/or modify
5 // it under the terms of the GNU General Public License as published by
6 // the Free Software Foundation; either version 3 of the License, or
7 // (at your option) any later version.
8 //
9 // This program is distributed in the hope that it will be useful,
10 // but WITHOUT ANY WARRANTY; without even the implied warranty of
11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 // GNU General Public License for more details.
13 //
14 // You should have received a copy of the GNU Lesser General Public License
15 // along with this program. If not, see <http://www.gnu.org/licenses/>.
16 //
17 // As a special exception, you may use this file as part of a free software
18 // library without restriction. Specifically, if other files instantiate
19 // templates or use macros or inline functions from this file, or you compile
20 // this file and link it with other files to produce an executable, this
21 // file does not by itself cause the resulting executable to be covered by
22 // the GNU General Public License. This exception does not however
23 // invalidate any other reasons why the executable file might be covered by
24 // the GNU General Public License.
25 //
26 // This exception applies only to the code released under the name GNU
27 // Common C++. If you copy code from other releases into a copy of GNU
28 // Common C++, as the General Public License permits, the exception does
29 // not apply to the code that you add in this way. To avoid misleading
30 // anyone as to the status of such modified files, you must delete
31 // this exception notice from them.
32 //
33 // If you write modifications of your own for GNU Common C++, it is your choice
34 // whether to permit this exception to apply to your modifications.
35 // If you do not wish that, delete this exception notice.
36 //
37 
43 #ifndef COMMONCPP_THREAD_H_
44 #define COMMONCPP_THREAD_H_
45 
46 #ifndef COMMONCPP_CONFIG_H_
47 #include <commoncpp/config.h>
48 #endif
49 
50 #ifndef COMMONCPP_STRING_H_
51 #include <commoncpp/string.h>
52 #endif
53 
54 #define ENTER_CRITICAL enterMutex();
55 #define LEAVE_CRITICAL leaveMutex();
56 
57 #include <time.h>
58 
59 namespace ost {
60 
61 class __EXPORT Mutex : protected ucommon::RecursiveMutex
62 {
63 public:
64  inline Mutex() : RecursiveMutex() {}
65 
66  inline void enterMutex(void)
68 
69  inline void leaveMutex(void)
71 
72  inline bool tryEnterMutex(void)
73  {return RecursiveMutex::lock(0l);}
74 
75  inline void enter(void)
77 
78  inline void leave(void)
80 
81  inline bool test(void)
82  {return RecursiveMutex::lock(0l);}
83 
84 };
85 
95 class __EXPORT MutexCounter : public Mutex
96 {
97 protected:
98  volatile int counter;
99 
100 public:
104  MutexCounter();
105 
112  MutexCounter(int initial);
113 
114  int operator++();
115  int operator--();
116 };
117 
141 class __EXPORT MutexLock
142 {
143 private:
144  Mutex& mutex;
145 
146 public:
152  inline MutexLock( Mutex& _mutex ) : mutex( _mutex )
153  { mutex.enterMutex(); }
154 
158  // this should be not-virtual
159  inline ~MutexLock()
160  { mutex.leaveMutex(); }
161 };
162 
163 class __EXPORT ThreadLock : protected ucommon::ThreadLock
164 {
165 public:
166  inline ThreadLock() : ucommon::ThreadLock() {}
167 
168  inline void readLock(void)
170 
171  inline void writeLock(void)
173 
174  inline void tryReadLock(void)
176 
177  inline void tryWriteLock(void)
179 
180  inline void unlock(void)
182 };
183 
204 class __EXPORT ReadLock
205 {
206 private:
207  ThreadLock& tl;
208 
209 public:
215  inline ReadLock( ThreadLock& _tl ) : tl( _tl )
216  { tl.readLock(); }
220  // this should be not-virtual
221  inline ~ReadLock()
222  { tl.unlock(); }
223 };
224 
245 class __EXPORT WriteLock
246 {
247 private:
248  ThreadLock& tl;
249 
250 public:
256  inline WriteLock( ThreadLock& _tl ) : tl( _tl )
257  { tl.writeLock(); }
261  // this should be not-virtual
262  inline ~WriteLock()
263  { tl.unlock(); }
264 };
265 
266 class __EXPORT Conditional : private ucommon::Conditional
267 {
268 public:
269  inline Conditional() : ucommon::Conditional() {}
270 
271  bool wait(timeout_t timeout, bool locked = false);
272 
273  void signal(bool broadcast);
274 
275  inline void enterMutex(void)
277 
278  inline void leaveMutex(void)
280 };
281 
282 class __EXPORT Semaphore : private ucommon::Semaphore
283 {
284 public:
285  inline Semaphore(unsigned size = 0) : ucommon::Semaphore(size) {}
286 
287  inline bool wait(timeout_t timeout)
288  {return ucommon::Semaphore::wait(timeout);}
289 
290  inline void wait(void)
292 
293  inline void post(void)
295 };
296 
316 class __EXPORT SemaphoreLock
317 {
318 private:
319  Semaphore& sem;
320 
321 public:
325  inline SemaphoreLock( Semaphore& _sem ) : sem( _sem )
326  { sem.wait(); }
330  // this should be not-virtual
331  inline ~SemaphoreLock()
332  { sem.post(); }
333 };
334 
335 class __EXPORT Event : private ucommon::TimedEvent
336 {
337 public:
338  inline Event() : ucommon::TimedEvent() {}
339 
340  inline void wait(void)
342 
343  inline bool wait(timeout_t timeout)
344  {return ucommon::TimedEvent::wait(timeout);}
345 
346  inline void signal(void)
348 
349  inline void reset(void)
351 
352  inline void set(timeout_t timeout = 0)
353  {ucommon::TimedEvent::set(timeout);}
354 };
355 
356 class __EXPORT Thread : protected ucommon::JoinableThread
357 {
358 public:
362  typedef enum Throw {
363  throwNothing,
364  throwObject,
365  throwException
366  } Throw;
367 
368 private:
369  friend class Slog;
370 
371  Throw exceptions;
372  bool detached, terminated;
373  Thread *parent;
374  size_t msgpos;
375  char msgbuf[128];
376 
377 public:
378  Thread(int pri = 0, size_t stack = 0);
379 
380  virtual ~Thread();
381 
382  inline void map(void)
383  {JoinableThread::map();}
384 
385  virtual void initial(void);
386  virtual void notify(Thread *thread);
387  virtual void final(void);
388  virtual void run(void) = 0;
389 
390  void terminate(void);
391  void finalize(void);
392 
393  void detach(void);
394  void start(void);
395  void exit(void);
396 
397  inline void join(void)
398  {JoinableThread::join();}
399 
400  inline void sync(void)
401  {Thread::exit();}
402 
403  static inline Thread *get(void)
404  {return (Thread *)JoinableThread::get();}
405 
406  inline static void yield(void)
408 
409  inline static void sleep(timeout_t msec = TIMEOUT_INF)
410  {ucommon::Thread::sleep(msec);}
411 
412  bool isRunning(void);
413 
414  bool isThread(void);
415 
421  static Throw getException(void);
422 
428  static void setException(Throw mode);
429 
433  inline pthread_t getId(void)
434  {return tid;}
435 };
436 
466 class __EXPORT SysTime
467 {
468 public:
469  static time_t getTime(time_t *tloc = NULL);
470  static time_t time(time_t *tloc)
471  {return getTime(tloc);}
472 
473  static int getTimeOfDay(struct timeval *tp);
474  static int gettimeofday(struct timeval *tp, struct timezone *)
475  {return getTimeOfDay(tp);}
476 
477  static struct tm *getLocalTime(const time_t *clock, struct tm *result);
478  static struct tm *locatime(const time_t *clock, struct tm *result)
479  {return getLocalTime(clock, result);}
480 
481  static struct tm *getGMTTime(const time_t *clock, struct tm *result);
482  static struct tm *gmtime(const time_t *clock, struct tm *result)
483  {return getGMTTime(clock, result);}
484 };
485 
496 class __EXPORT TimerPort
497 {
498 #ifndef _MSWINDOWS_
499  struct timeval timer;
500 #else
501  DWORD timer;
502 #endif
503  bool active;
504 
505 public:
512  TimerPort();
513 
522  void setTimer(timeout_t timeout = 0);
523 
533  void incTimer(timeout_t timeout);
534 
544  void decTimer(timeout_t timeout);
545 
550  void sleepTimer(void);
551 
557  void endTimer(void);
558 
570  timeout_t getTimer(void) const;
571 
581  timeout_t getElapsed(void) const;
582 };
583 
584 #ifndef _MSWINDOWS_
585 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
586 #endif
587 
588 #if !defined(_MSWINDOWS_) || defined(_MSTHREADS_)
589 inline struct tm *localtime_r(const time_t *t, struct tm *b)
590  {return SysTime::getLocalTime(t, b);}
591 
592 inline char *ctime_r(const time_t *t, char *buf)
593  {return ctime(t);}
594 
595 inline struct tm *gmtime_r(const time_t *t, struct tm *b)
596  {return SysTime::getGMTTime(t, b);}
597 
598 inline char *asctime_r(const struct tm *tm, char *b)
599  {return asctime(tm);}
600 #endif
601 
602 inline Thread *getThread(void)
603  {return Thread::get();}
604 
626 #ifdef _MSWINDOWS_
627 class __EXPORT Buffer : public Mutex
628 #else
629 class __EXPORT Buffer : public Conditional
630 #endif
631 {
632 private:
633 #ifdef _MSWINDOWS_
634  HANDLE sem_head, sem_tail;
635 #endif
636  size_t _size;
637  size_t _used;
638 
639 protected:
645  virtual size_t onPeek(void *buf) = 0;
646 
652  virtual size_t onWait(void *buf) = 0;
653 
659  virtual size_t onPost(void *buf) = 0;
660 
661 public:
666  static const size_t timeout;
667 
672  Buffer(size_t capacity);
677  virtual ~Buffer();
678 
683  inline size_t getSize(void)
684  {return _size;}
685 
692  inline size_t getUsed(void)
693  {return _used;}
694 
704  size_t wait(void *buf, timeout_t timeout = 0);
705 
714  size_t post(void *buf, timeout_t timeout = 0);
715 
722  size_t peek(void *buf);
723 
728  virtual bool isValid(void);
729 };
730 
738 class __EXPORT FixedBuffer : public Buffer
739 {
740 private:
741  char *buf, *head, *tail;
742  size_t objsize;
743 
744 protected:
750  size_t onPeek(void *buf);
751 
757  size_t onWait(void *buf);
758 
764  size_t onPost(void *buf);
765 
766 public:
774  FixedBuffer(size_t capacity, size_t objsize);
775 
782  FixedBuffer(const FixedBuffer &fb);
783 
787  virtual ~FixedBuffer();
788 
789  FixedBuffer &operator=(const FixedBuffer &fb);
790 
791  bool isValid(void);
792 };
793 
809 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
810 {
811 private:
812  void run(void); // private run method
813 
814 protected:
815  typedef struct _data {
816  struct _data *next;
817  unsigned len;
818  char data[1];
819  } data_t;
820 
821  timeout_t timeout;
822  bool started;
823 
824  data_t *first, *last; // head/tail of list
825 
826  String name;
827 
828  /*
829  * Overloading of final(). It demarks Semaphore to avoid deadlock.
830  */
831  virtual void final();
832 
837  virtual void startQueue(void);
838 
844  virtual void stopQueue(void);
845 
849  virtual void onTimer(void);
850 
859  virtual void runQueue(void *data) = 0;
860 
861 public:
869  ThreadQueue(const char *id, int pri, size_t stack = 0);
870 
874  virtual ~ThreadQueue();
875 
883  void setTimer(timeout_t timeout);
884 
893  void post(const void *data, unsigned len);
894 };
895 
896 
898 inline size_t get(Buffer &b, void *o, timeout_t t = 0)
899  {return b.wait(o, t);}
900 
902 inline size_t put(Buffer &b, void *o, timeout_t t = 0)
903  {return b.post(o, t);}
904 
906 inline size_t peek(Buffer &b, void *o)
907  {return b.peek(o);}
908 
909 } // namespace ost
910 
911 #endif
The conditional is a common base for other thread synchronizing classes.
Definition: thread.h:86
void wait(void)
Wait until the semphore usage count is less than the thread limit.
static void sleep(timeout_t timeout)
Sleep current thread for a specified time period.
void set(void)
Set (update) the timer with current time.
Somewhat generic queue processing class to establish a producer consumer queue.
Definition: thread.h:809
void start(DetachedThread *thread, int priority=0)
Convenience function to start a detached thread.
Definition: thread.h:1878
The Mutex Counter is a counter variable which can safely be incremented or decremented by multiple th...
Definition: thread.h:95
A copy-on-write string class that operates by reference count.
Definition: string.h:82
Common namespace for all ucommon objects.
Definition: access.h:46
void signal(void)
Signal pending event.
Definition: address.h:58
void release(rexlock_t &lock)
Convenience function to release a shared recursive mutex lock.
Definition: thread.h:2063
The WriteLock class is used to protect a section of code through a ThreadLock for "write" access to t...
Definition: thread.h:245
static void yield(void)
Yield execution context of the current thread.
size_t getUsed(void)
Return the current capacity in use for the buffer.
Definition: thread.h:692
ReadLock(ThreadLock &_tl)
Wait for read access.
Definition: thread.h:215
void lock(void)
Lock the conditional's supporting mutex.
Definition: thread.h:148
Timer ports are used to provide synchronized timing events when managed under a "service thread" such...
Definition: thread.h:496
size_t post(void *buf, timeout_t timeout=0)
Post an object into the buffer and enable a waiting thread to receive it.
void unlock(ExclusiveAccess &object)
Convenience function to unlock an exclusive object through it's protocol.
Definition: access.h:246
void release(void)
Release the semaphore after waiting for it.
MutexLock(Mutex &_mutex)
Acquire the mutex.
Definition: thread.h:152
This class is used to access non-reentrant date and time functions in the standard C library...
Definition: thread.h:466
A child thread object that may be joined by parent.
Definition: thread.h:1428
A portable counting semaphore class.
Definition: thread.h:883
A buffer class that holds a known capacity of fixed sized objects defined during creation.
Definition: thread.h:738
~SemaphoreLock()
Post the semaphore automatically.
Definition: thread.h:331
void wait(semaphore_t &semaphore, timeout_t timeout=Timer::inf)
Convenience function to wait on a semaphore.
Definition: thread.h:1933
Event notification to manage scheduled realtime threads.
Definition: thread.h:395
~WriteLock()
Post the semaphore automatically.
Definition: thread.h:262
size_t peek(Buffer &b, void *o)
Definition: thread.h:906
Common C++ generic string class.
Portable recursive exclusive lock.
Definition: thread.h:484
The ReadLock class is used to protect a section of code through a ThreadLock for "read" access to the...
Definition: thread.h:204
void wait(void)
A simple wait until triggered.
~MutexLock()
Release the mutex automatically.
Definition: thread.h:159
void release(void)
Release the lock.
static const size_t timeout
value to return when a timed operation returned with a timeout.
Definition: thread.h:666
A generic and portable implimentation of Read/Write locking.
Definition: thread.h:528
The SemaphoreLock class is used to protect a section of code through a semaphore so that only x insta...
Definition: thread.h:316
size_t getSize(void)
Return the capacity of the buffer as specified at creation.
Definition: thread.h:683
void unlock(void)
Unlock the conditional's supporting mutex.
Definition: thread.h:154
size_t peek(void *buf)
Peek at the current content (first object) in the buffer.
void lock(rexlock_t &lock)
Convenience function to lock a shared recursive mutex lock.
Definition: thread.h:2056
void modify(void)
Exclusive mode write thread scheduling.
The MutexLock class is used to protect a section of code so that at any given time only a single thre...
Definition: thread.h:141
The buffer class represents an IPC service that is built upon a buffer of fixed capacity that can be ...
Definition: thread.h:629
~ReadLock()
Post the semaphore automatically.
Definition: thread.h:221
void reset(void)
Reset triggered conditional.
unsigned long timeout_t
Typedef for millisecond timer values.
Definition: platform.h:334
void access(void)
Access mode shared thread scheduling.
WriteLock(ThreadLock &_tl)
Wait for write access.
Definition: thread.h:256
size_t put(Buffer &b, void *o, timeout_t t=0)
Definition: thread.h:902
SemaphoreLock(Semaphore &_sem)
Wait for the semaphore.
Definition: thread.h:325