ucommon
thread.h
Go to the documentation of this file.
1 // Copyright (C) 1999-2005 Open Source Telecom Corporation.
2 // Copyright (C) 2006-2010 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 General Public License
15 // along with this program; if not, write to the Free Software
16 // Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17 
23 #ifndef COMMONCPP_THREAD_H_
24 #define COMMONCPP_THREAD_H_
25 
26 #ifndef COMMONCPP_CONFIG_H_
27 #include <commoncpp/config.h>
28 #endif
29 
30 #ifndef COMMONCPP_STRING_H_
31 #include <commoncpp/string.h>
32 #endif
33 
34 #define ENTER_CRITICAL enterMutex();
35 #define LEAVE_CRITICAL leaveMutex();
36 
37 NAMESPACE_COMMONCPP
38 
39 class __EXPORT Mutex : protected ucommon::RecursiveMutex
40 {
41 public:
42  inline Mutex() : RecursiveMutex() {};
43 
44  inline void enterMutex(void)
46 
47  inline void leaveMutex(void)
49 
50  inline bool tryEnterMutex(void)
51  {return RecursiveMutex::lock(0l);};
52 
53  inline void enter(void)
55 
56  inline void leave(void)
58 
59  inline bool test(void)
60  {return RecursiveMutex::lock(0l);};
61 
62 };
63 
73 class __EXPORT MutexCounter : public Mutex
74 {
75 protected:
76  volatile int counter;
77 
78 public:
82  MutexCounter();
83 
90  MutexCounter(int initial);
91 
92  int operator++();
93  int operator--();
94 };
95 
119 class __EXPORT MutexLock
120 {
121 private:
122  Mutex& mutex;
123 
124 public:
130  inline MutexLock( Mutex& _mutex ) : mutex( _mutex )
131  { mutex.enterMutex(); }
132 
136  // this should be not-virtual
137  inline ~MutexLock()
138  { mutex.leaveMutex(); }
139 };
140 
141 class __EXPORT ThreadLock : protected ucommon::ThreadLock
142 {
143 public:
144  inline ThreadLock() : ucommon::ThreadLock() {};
145 
146  inline void readLock(void)
148 
149  inline void writeLock(void)
151 
152  inline void tryReadLock(void)
154 
155  inline void tryWriteLock(void)
157 
158  inline void unlock(void)
160 };
161 
182 class __EXPORT ReadLock
183 {
184 private:
185  ThreadLock& tl;
186 
187 public:
193  inline ReadLock( ThreadLock& _tl ) : tl( _tl )
194  { tl.readLock(); }
198  // this should be not-virtual
199  inline ~ReadLock()
200  { tl.unlock(); }
201 };
202 
223 class __EXPORT WriteLock
224 {
225 private:
226  ThreadLock& tl;
227 
228 public:
234  inline WriteLock( ThreadLock& _tl ) : tl( _tl )
235  { tl.writeLock(); }
239  // this should be not-virtual
240  inline ~WriteLock()
241  { tl.unlock(); }
242 };
243 
244 class __EXPORT Conditional : private ucommon::Conditional
245 {
246 public:
247  inline Conditional() : ucommon::Conditional() {};
248 
249  bool wait(timeout_t timeout, bool locked = false);
250 
251  void signal(bool broadcast);
252 
253  inline void enterMutex(void)
255 
256  inline void leaveMutex(void)
258 };
259 
260 class __EXPORT Semaphore : private ucommon::Semaphore
261 {
262 public:
263  inline Semaphore(unsigned size=0) : ucommon::Semaphore(size) {};
264 
265  inline bool wait(timeout_t timeout = 0)
266  {return ucommon::Semaphore::wait(timeout);};
267 
268  inline void post(void)
270 };
271 
291 class __EXPORT SemaphoreLock
292 {
293 private:
294  Semaphore& sem;
295 
296 public:
300  inline SemaphoreLock( Semaphore& _sem ) : sem( _sem )
301  { sem.wait(); }
305  // this should be not-virtual
306  inline ~SemaphoreLock()
307  { sem.post(); }
308 };
309 
310 class __EXPORT Event : private ucommon::TimedEvent
311 {
312 public:
313  inline Event() : TimedEvent() {};
314 
315  inline void wait(void)
316  {ucommon::TimedEvent::wait(Timer::inf);};
317 
318  inline bool wait(timeout_t timeout)
319  {return ucommon::TimedEvent::wait(timeout);};
320 
321  inline void signal(void)
323 
324  inline void reset(void)
326 };
327 
328 class __EXPORT Thread : protected ucommon::JoinableThread
329 {
330 public:
334  typedef enum Throw {
335  throwNothing,
336  throwObject,
337  throwException
338  } Throw;
339 
340 private:
341  friend class Slog;
342 
343  Throw exceptions;
344  bool detached, terminated;
345  Thread *parent;
346  size_t msgpos;
347  char msgbuf[128];
348 
349 public:
350  Thread(int pri = 0, size_t stack = 0);
351 
352  virtual ~Thread();
353 
354  inline void map(void)
355  {JoinableThread::map();};
356 
357  virtual void initial(void);
358  virtual void notify(Thread *thread);
359  virtual void final(void);
360  virtual void run(void) = 0;
361 
362  void terminate(void);
363  void finalize(void);
364 
365  void detach(void);
366  void start(void);
367  void exit(void);
368 
369  inline void join(void)
371 
372  inline void sync(void)
373  {Thread::exit();};
374 
375  static inline Thread *get(void)
376  {return (Thread *)JoinableThread::get();};
377 
378  inline static void yield(void)
380 
381  inline static void sleep(timeout_t msec = TIMEOUT_INF)
382  {ucommon::Thread::sleep(msec);};
383 
384  bool isRunning(void);
385 
386  bool isThread(void);
387 
393  static Throw getException(void);
394 
400  static void setException(Throw mode);
401 
405  inline pthread_t getId(void)
406  {return tid;};
407 };
408 
438 class __EXPORT SysTime
439 {
440 public:
441  static time_t getTime(time_t *tloc = NULL);
442  static time_t time(time_t *tloc)
443  { return getTime(tloc); };
444 
445  static int getTimeOfDay(struct timeval *tp);
446  static int gettimeofday(struct timeval *tp, struct timezone *)
447  { return getTimeOfDay(tp); };
448 
449  static struct tm *getLocalTime(const time_t *clock, struct tm *result);
450  static struct tm *locatime(const time_t *clock, struct tm *result)
451  { return getLocalTime(clock, result); };
452 
453  static struct tm *getGMTTime(const time_t *clock, struct tm *result);
454  static struct tm *gmtime(const time_t *clock, struct tm *result)
455  { return getGMTTime(clock, result);};
456 };
457 
468 class __EXPORT TimerPort
469 {
470 #ifndef _MSWINDOWS_
471  struct timeval timer;
472 #else
473  DWORD timer;
474 #endif
475  bool active;
476 
477 public:
484  TimerPort();
485 
494  void setTimer(timeout_t timeout = 0);
495 
505  void incTimer(timeout_t timeout);
506 
516  void decTimer(timeout_t timeout);
517 
522  void sleepTimer(void);
523 
529  void endTimer(void);
530 
542  timeout_t getTimer(void) const;
543 
553  timeout_t getElapsed(void) const;
554 };
555 
556 #ifndef _MSWINDOWS_
557 struct timespec *getTimeout(struct timespec *spec, timeout_t timeout);
558 #endif
559 
560 inline struct tm *localtime_r(const time_t *t, struct tm *b)
561  {return SysTime::getLocalTime(t, b);}
562 
563 inline char *ctime_r(const time_t *t, char *buf)
564  {return ctime(t);}
565 
566 inline struct tm *gmtime_r(const time_t *t, struct tm *b)
567  {return SysTime::getGMTTime(t, b);}
568 
569 inline char *asctime_r(const struct tm *tm, char *b)
570  {return asctime(tm);}
571 
572 inline Thread *getThread(void)
573  {return Thread::get();}
574 
596 #ifdef _MSWINDOWS_
597 class __EXPORT Buffer : public Mutex
598 #else
599 class __EXPORT Buffer : public Conditional
600 #endif
601 {
602 private:
603 #ifdef _MSWINDOWS_
604  HANDLE sem_head, sem_tail;
605 #endif
606  size_t _size;
607  size_t _used;
608 
609 protected:
615  virtual size_t onPeek(void *buf) = 0;
616 
622  virtual size_t onWait(void *buf) = 0;
623 
629  virtual size_t onPost(void *buf) = 0;
630 
631 public:
636  static const size_t timeout;
637 
642  Buffer(size_t capacity);
647  virtual ~Buffer();
648 
653  inline size_t getSize(void)
654  {return _size;};
655 
662  inline size_t getUsed(void)
663  {return _used;};
664 
674  size_t wait(void *buf, timeout_t timeout = 0);
675 
684  size_t post(void *buf, timeout_t timeout = 0);
685 
692  size_t peek(void *buf);
693 
698  virtual bool isValid(void);
699 };
700 
708 class __EXPORT FixedBuffer : public Buffer
709 {
710 private:
711  char *buf, *head, *tail;
712  size_t objsize;
713 
714 protected:
720  size_t onPeek(void *buf);
721 
727  size_t onWait(void *buf);
728 
734  size_t onPost(void *buf);
735 
736 public:
744  FixedBuffer(size_t capacity, size_t objsize);
745 
752  FixedBuffer(const FixedBuffer &fb);
753 
757  virtual ~FixedBuffer();
758 
759  FixedBuffer &operator=(const FixedBuffer &fb);
760 
761  bool isValid(void);
762 };
763 
779 class __EXPORT ThreadQueue : public Mutex, public Thread, public Semaphore
780 {
781 private:
782  void run(void); // private run method
783 
784 protected:
785  typedef struct _data {
786  struct _data *next;
787  unsigned len;
788  char data[1];
789  } data_t;
790 
791  timeout_t timeout;
792  bool started;
793 
794  data_t *first, *last; // head/tail of list
795 
796  String name;
797 
798  /*
799  * Overloading of final(). It demarks Semaphore to avoid deadlock.
800  */
801  virtual void final();
802 
807  virtual void startQueue(void);
808 
814  virtual void stopQueue(void);
815 
819  virtual void onTimer(void);
820 
829  virtual void runQueue(void *data) = 0;
830 
831 public:
839  ThreadQueue(const char *id, int pri, size_t stack = 0);
840 
844  virtual ~ThreadQueue();
845 
853  void setTimer(timeout_t timeout);
854 
863  void post(const void *data, unsigned len);
864 };
865 
866 
868 inline size_t get(Buffer &b, void *o, timeout_t t = 0)
869  {return b.wait(o, t);}
870 
872 inline size_t put(Buffer &b, void *o, timeout_t t = 0)
873  {return b.post(o, t);}
874 
876 inline size_t peek(Buffer &b, void *o)
877  {return b.peek(o);}
878 
879 END_NAMESPACE
880 
881 #endif