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 public:
65  inline Mutex() : RecursiveMutex() {}
66 
67  inline void enterMutex(void)
69 
70  inline void leaveMutex(void)
72 
73  inline bool tryEnterMutex(void)
74  {return RecursiveMutex::lock(0l);}
75 
76  inline void enter(void)
78 
79  inline void leave(void)
81 
82  inline bool test(void)
83  {return RecursiveMutex::lock(0l);}
84 
85 };
86 
96 class __EXPORT MutexCounter : public Mutex
97 {
98 protected:
99  volatile int counter;
100 
101 public:
105  MutexCounter();
106 
113  MutexCounter(int initial);
114 
115  int operator++();
116  int operator--();
117 };
118 
142 class __EXPORT MutexLock
143 {
144 private:
145  Mutex& mutex;
146 
147 public:
153  inline MutexLock( Mutex& _mutex ) : mutex( _mutex )
154  { mutex.enterMutex(); }
155 
159  // this should be not-virtual
160  inline ~MutexLock()
161  { mutex.leaveMutex(); }
162 };
163 
164 class __EXPORT ThreadLock : protected ucommon::ThreadLock
165 {
166 public:
167  inline ThreadLock() : ucommon::ThreadLock() {}
168 
169  inline void readLock(void)
171 
172  inline void writeLock(void)
174 
175  inline void tryReadLock(void)
177 
178  inline void tryWriteLock(void)
180 
181  inline void unlock(void)
183 };
184 
205 class __EXPORT ReadLock
206 {
207 private:
208  ThreadLock& tl;
209 
210 public:
216  inline ReadLock( ThreadLock& _tl ) : tl( _tl )
217  { tl.readLock(); }
221  // this should be not-virtual
222  inline ~ReadLock()
223  { tl.unlock(); }
224 };
225 
246 class __EXPORT WriteLock
247 {
248 private:
249  ThreadLock& tl;
250 
251 public:
257  inline WriteLock( ThreadLock& _tl ) : tl( _tl )
258  { tl.writeLock(); }
262  // this should be not-virtual
263  inline ~WriteLock()
264  { tl.unlock(); }
265 };
266 
267 class __EXPORT Conditional : private ucommon::Conditional
268 {
269 public:
270  inline Conditional() : ucommon::Conditional() {}
271 
272  bool wait(timeout_t timeout, bool locked = false);
273 
274  void signal(bool broadcast);
275 
276  inline void enterMutex(void)
278 
279  inline void leaveMutex(void)
281 };
282 
283 class __EXPORT Semaphore : private ucommon::Semaphore
284 {
285 public:
286  inline Semaphore(unsigned size = 0) : ucommon::Semaphore(size) {}
287 
288  inline bool wait(timeout_t timeout)
289  {return ucommon::Semaphore::wait(timeout);}
290 
291  inline void wait(void)
293 
294  inline void post(void)
296 };
297 
317 class __EXPORT SemaphoreLock
318 {
319 private:
320  Semaphore& sem;
321 
322 public:
326  inline SemaphoreLock( Semaphore& _sem ) : sem( _sem )
327  { sem.wait(); }
331  // this should be not-virtual
332  inline ~SemaphoreLock()
333  { sem.post(); }
334 };
335 
336 class __EXPORT Event : private ucommon::TimedEvent
337 {
338 public:
339  inline Event() : ucommon::TimedEvent() {}
340 
341  inline void wait(void)
343 
344  inline bool wait(timeout_t timeout)
345  {return ucommon::TimedEvent::wait(timeout);}
346 
347  inline void signal(void)
349 
350  inline void reset(void)
352 
353  inline void set(timeout_t timeout = 0)
354  {ucommon::TimedEvent::set(timeout);}
355 };
356 
357 class __EXPORT Thread : protected ucommon::JoinableThread
358 {
359 public:
363  typedef enum Throw {
364  throwNothing,
365  throwObject,
366  throwException
367  } Throw;
368 
369 private:
370  friend class Slog;
371 
372  Throw exceptions;
373  bool detached, terminated;
374  Thread *parent;
375  size_t msgpos;
376  char msgbuf[128];
377 
378 public:
379  Thread(int pri = 0, size_t stack = 0);
380 
381  virtual ~Thread();
382 
383  inline void map(void)
384  {JoinableThread::map();}
385 
386  virtual void initial(void);
387  virtual void notify(Thread *thread);
388  virtual void final(void);
389  virtual void run(void) = 0;
390 
391  void terminate(void);
392  void finalize(void);
393 
394  void detach(void);
395  void start(void);
396  void exit(void);
397 
398  inline void join(void)
399  {JoinableThread::join();}
400 
401  inline void sync(void)
402  {Thread::exit();}
403 
404  static inline Thread *get(void)
405  {return (Thread *)JoinableThread::get();}
406 
407  inline static void yield(void)
409 
410  inline static void sleep(timeout_t msec = TIMEOUT_INF)
411  {ucommon::Thread::sleep(msec);}
412 
413  bool isRunning(void);
414 
415  bool isThread(void);
416 
422  static Throw getException(void);
423 
429  static void setException(Throw mode);
430 
434  inline pthread_t getId(void)
435  {return tid;}
436 };
437 
467 class __EXPORT SysTime
468 {
469 public:
470  static time_t getTime(time_t *tloc = NULL);
471  static time_t time(time_t *tloc)
472  {return getTime(tloc);}
473 
474  static int getTimeOfDay(struct timeval *tp);
475  static int gettimeofday(struct timeval *tp, struct timezone *)
476  {return getTimeOfDay(tp);}
477 
478  static struct tm *getLocalTime(const time_t *clock, struct tm *result);
479  static struct tm *locatime(const time_t *clock, struct tm *result)
480  {return getLocalTime(clock, result);}
481 
482  static struct tm *getGMTTime(const time_t *clock, struct tm *result);
483  static struct tm *gmtime(const time_t *clock, struct tm *result)
484  {return getGMTTime(clock, result);}
485 };
486 
497 class __EXPORT TimerPort
498 {
499 #ifndef _MSWINDOWS_
500  struct timeval timer;
501 #else
502  DWORD timer;
503 #endif
504  bool active;
505 
506 public:
513  TimerPort();
514 
523  void setTimer(timeout_t timeout = 0);
524 
534  void incTimer(timeout_t timeout);
535 
545  void decTimer(timeout_t timeout);
546 
551  void sleepTimer(void);
552 
558  void endTimer(void);
559 
571  timeout_t getTimer(void) const;
572 
582  timeout_t getElapsed(void) const;
583 };
584 
585 #ifndef _MSWINDOWS_
586 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
587 #endif
588 
589 #if !defined(_MSWINDOWS_) || defined(_MSTHREADS_)
590 inline struct tm *localtime_r(const time_t *t, struct tm *b)
591  {return SysTime::getLocalTime(t, b);}
592 
593 inline char *ctime_r(const time_t *t, char *buf)
594  {return ctime(t);}
595 
596 inline struct tm *gmtime_r(const time_t *t, struct tm *b)
597  {return SysTime::getGMTTime(t, b);}
598 
599 inline char *asctime_r(const struct tm *tm, char *b)
600  {return asctime(tm);}
601 #endif
602 
603 inline Thread *getThread(void)
604  {return Thread::get();}
605 
627 #ifdef _MSWINDOWS_
628 class __EXPORT Buffer : public Mutex
629 #else
630 class __EXPORT Buffer : public Conditional
631 #endif
632 {
633 private:
634 #ifdef _MSWINDOWS_
635  HANDLE sem_head, sem_tail;
636 #endif
637  size_t _size;
638  size_t _used;
639 
640 protected:
646  virtual size_t onPeek(void *buf) = 0;
647 
653  virtual size_t onWait(void *buf) = 0;
654 
660  virtual size_t onPost(void *buf) = 0;
661 
662 public:
667  static const size_t timeout;
668 
673  Buffer(size_t capacity);
678  virtual ~Buffer();
679 
684  inline size_t getSize(void)
685  {return _size;}
686 
693  inline size_t getUsed(void)
694  {return _used;}
695 
705  size_t wait(void *buf, timeout_t timeout = 0);
706 
715  size_t post(void *buf, timeout_t timeout = 0);
716 
723  size_t peek(void *buf);
724 
729  virtual bool isValid(void);
730 };
731 
739 class __EXPORT FixedBuffer : public Buffer
740 {
741 private:
742  char *buf, *head, *tail;
743  size_t objsize;
744 
745 protected:
751  size_t onPeek(void *buf);
752 
758  size_t onWait(void *buf);
759 
765  size_t onPost(void *buf);
766 
767 public:
775  FixedBuffer(size_t capacity, size_t objsize);
776 
783  FixedBuffer(const FixedBuffer &fb);
784 
788  virtual ~FixedBuffer();
789 
790  FixedBuffer &operator=(const FixedBuffer &fb);
791 
792  bool isValid(void);
793 };
794 
810 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
811 {
812 private:
813  void run(void); // private run method
814 
815 protected:
816  typedef struct _data {
817  struct _data *next;
818  unsigned len;
819  char data[1];
820  } data_t;
821 
822  timeout_t timeout;
823  bool started;
824 
825  data_t *first, *last; // head/tail of list
826 
827  String name;
828 
829  /*
830  * Overloading of final(). It demarks Semaphore to avoid deadlock.
831  */
832  virtual void final();
833 
838  virtual void startQueue(void);
839 
845  virtual void stopQueue(void);
846 
850  virtual void onTimer(void);
851 
860  virtual void runQueue(void *data) = 0;
861 
862 public:
870  ThreadQueue(const char *id, int pri, size_t stack = 0);
871 
875  virtual ~ThreadQueue();
876 
884  void setTimer(timeout_t timeout);
885 
894  void post(const void *data, unsigned len);
895 };
896 
897 
899 inline size_t get(Buffer &b, void *o, timeout_t t = 0)
900  {return b.wait(o, t);}
901 
903 inline size_t put(Buffer &b, void *o, timeout_t t = 0)
904  {return b.post(o, t);}
905 
907 inline size_t peek(Buffer &b, void *o)
908  {return b.peek(o);}
909 
910 } // namespace ost
911 
912 #endif
The conditional is a common base for other thread synchronizing classes.
Definition: thread.h:87
void reset(void)
Reset triggered conditional.
Portable recursive exclusive lock.
Definition: thread.h:480
Event notification to manage scheduled realtime threads.
Definition: thread.h:391
Somewhat generic queue processing class to establish a producer consumer queue.
Definition: thread.h:810
The Mutex Counter is a counter variable which can safely be incremented or decremented by multiple th...
Definition: thread.h:96
Definition: address.h:59
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:83
The WriteLock class is used to protect a section of code through a ThreadLock for "write" access to t...
Definition: thread.h:246
size_t getUsed(void)
Return the current capacity in use for the buffer.
Definition: thread.h:693
ReadLock(ThreadLock &_tl)
Wait for read access.
Definition: thread.h:216
void start(DetachedThread *thread, int priority=0)
Convenience function to start a detached thread.
Definition: thread.h:1874
void lock(void)
Lock the conditional's supporting mutex.
Definition: thread.h:143
Timer ports are used to provide synchronized timing events when managed under a "service thread" such...
Definition: thread.h:497
void release(void)
Release the semaphore after waiting for it.
void wait(void)
A simple wait until triggered.
size_t post(void *buf, timeout_t timeout=0)
Post an object into the buffer and enable a waiting thread to receive it.
MutexLock(Mutex &_mutex)
Acquire the mutex.
Definition: thread.h:153
This class is used to access non-reentrant date and time functions in the standard C library...
Definition: thread.h:467
A child thread object that may be joined by parent.
Definition: thread.h:1424
A buffer class that holds a known capacity of fixed sized objects defined during creation.
Definition: thread.h:739
~SemaphoreLock()
Post the semaphore automatically.
Definition: thread.h:332
Common namespace for all ucommon objects.
Definition: access.h:47
Common C++ generic string class.
~WriteLock()
Post the semaphore automatically.
Definition: thread.h:263
size_t peek(Buffer &b, void *o)
Definition: thread.h:907
static void sleep(timeout_t timeout)
Sleep current thread for a specified time period.
A generic and portable implimentation of Read/Write locking.
Definition: thread.h:524
void wait(semaphore_t &semaphore, timeout_t timeout=Timer::inf)
Convenience function to wait on a semaphore.
Definition: thread.h:1929
The ReadLock class is used to protect a section of code through a ThreadLock for "read" access to the...
Definition: thread.h:205
void unlock(ExclusiveAccess &object)
Convenience function to unlock an exclusive object through it's protocol.
Definition: access.h:262
~MutexLock()
Release the mutex automatically.
Definition: thread.h:160
void set(void)
Set (update) the timer with current time.
static const size_t timeout
value to return when a timed operation returned with a timeout.
Definition: thread.h:667
The SemaphoreLock class is used to protect a section of code through a semaphore so that only x insta...
Definition: thread.h:317
size_t getSize(void)
Return the capacity of the buffer as specified at creation.
Definition: thread.h:684
void unlock(void)
Unlock the conditional's supporting mutex.
Definition: thread.h:149
size_t peek(void *buf)
Peek at the current content (first object) in the buffer.
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:142
void release(rexlock_t &lock)
Convenience function to release a shared recursive mutex lock.
Definition: thread.h:2059
The buffer class represents an IPC service that is built upon a buffer of fixed capacity that can be ...
Definition: thread.h:630
~ReadLock()
Post the semaphore automatically.
Definition: thread.h:222
A portable counting semaphore class.
Definition: thread.h:879
void signal(void)
Signal pending event.
void access(void)
Access mode shared thread scheduling.
WriteLock(ThreadLock &_tl)
Wait for write access.
Definition: thread.h:257
void lock(rexlock_t &lock)
Convenience function to lock a shared recursive mutex lock.
Definition: thread.h:2052
static void yield(void)
Yield execution context of the current thread.
size_t put(Buffer &b, void *o, timeout_t t=0)
Definition: thread.h:903
SemaphoreLock(Semaphore &_sem)
Wait for the semaphore.
Definition: thread.h:326
void release(void)
Release the lock.