ucommon
thread.h
Go to the documentation of this file.
1 // Copyright (C) 2006-2010 David Sugar, Tycho Softworks.
2 //
3 // This file is part of GNU uCommon C++.
4 //
5 // GNU uCommon C++ is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published
7 // by the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // GNU uCommon C++ 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 Lesser General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with GNU uCommon C++. If not, see <http://www.gnu.org/licenses/>.
17 
53 #ifndef _UCOMMON_THREAD_H_
54 #define _UCOMMON_THREAD_H_
55 
56 #ifndef _UCOMMON_CPR_H_
57 #include <ucommon/cpr.h>
58 #endif
59 
60 #ifndef _UCOMMON_ACCESS_H_
61 #include <ucommon/access.h>
62 #endif
63 
64 #ifndef _UCOMMON_TIMERS_H_
65 #include <ucommon/timers.h>
66 #endif
67 
68 #ifndef _UCOMMON_MEMORY_H_
69 #include <ucommon/memory.h>
70 #endif
71 
72 NAMESPACE_UCOMMON
73 
74 class SharedPointer;
75 
86 class __EXPORT Conditional
87 {
88 private:
89  friend class ConditionalAccess;
90 
91 #if defined(_MSCONDITIONAL_)
92  CRITICAL_SECTION mutex;
93  CONDITION_VARIABLE cond;
94 #elif defined(_MSWINDOWS_)
95  enum {SIGNAL = 0, BROADCAST = 1};
96  HANDLE events[2];
97  unsigned waiting;
98  CRITICAL_SECTION mlock;
99  CRITICAL_SECTION mutex;
100 #else
101 #ifndef __PTH__
102  class __LOCAL attribute
103  {
104  public:
105  pthread_condattr_t attr;
106  attribute();
107  };
108 
109  __LOCAL static attribute attr;
110 #endif
111 
112  pthread_cond_t cond;
113  pthread_mutex_t mutex;
114 #endif
115 
116 protected:
117  friend class TimedEvent;
118 
124  bool wait(timeout_t timeout);
125 
131  bool wait(struct timespec *timeout);
132 
133 #ifdef _MSWINDOWS_
134  inline void lock(void)
135  {EnterCriticalSection(&mutex);};
136 
137  inline void unlock(void)
138  {LeaveCriticalSection(&mutex);};
139 
140  void wait(void);
141  void signal(void);
142  void broadcast(void);
143 
144 #else
145 
148  inline void lock(void)
149  {pthread_mutex_lock(&mutex);};
150 
154  inline void unlock(void)
155  {pthread_mutex_unlock(&mutex);};
156 
160  inline void wait(void)
161  {pthread_cond_wait(&cond, &mutex);};
162 
166  inline void signal(void)
167  {pthread_cond_signal(&cond);};
168 
172  inline void broadcast(void)
173  {pthread_cond_broadcast(&cond);};
174 #endif
175 
179  Conditional();
180 
184  ~Conditional();
185 
186 public:
187 #if !defined(_MSWINDOWS_) && !defined(__PTH__)
188 
193  static inline pthread_condattr_t *initializer(void)
194  {return &attr.attr;};
195 #endif
196 
203  static void gettimeout(timeout_t timeout, struct timespec *hires);
204 };
205 
213 class __EXPORT ConditionalAccess : private Conditional
214 {
215 protected:
216 #if defined _MSCONDITIONAL_
217  CONDITION_VARIABLE bcast;
218 #elif !defined(_MSWINDOWS_)
219  pthread_cond_t bcast;
220 #endif
221 
222  unsigned pending, waiting, sharing;
223 
229  bool waitSignal(timeout_t timeout);
230 
236  bool waitBroadcast(timeout_t timeout);
237 
238 
244  bool waitSignal(struct timespec *timeout);
245 
251  bool waitBroadcast(struct timespec *timeout);
252 
259  inline static void gettimeout(timeout_t timeout, struct timespec *hires)
260  {Conditional::gettimeout(timeout, hires);};
261 
262 
263 #ifdef _MSWINDOWS_
264  inline void lock(void)
265  {EnterCriticalSection(&mutex);};
266 
267  inline void unlock(void)
268  {LeaveCriticalSection(&mutex);};
269 
270  void waitSignal(void);
271  void waitBroadcast(void);
272 
273  inline void signal(void)
274  {Conditional::signal();};
275 
276  inline void broadcast(void)
277  {Conditional::broadcast();};
278 
279 #else
280 
283  inline void lock(void)
284  {pthread_mutex_lock(&mutex);};
285 
289  inline void unlock(void)
290  {pthread_mutex_unlock(&mutex);};
291 
295  inline void waitSignal(void)
296  {pthread_cond_wait(&cond, &mutex);};
297 
301  inline void waitBroadcast(void)
302  {pthread_cond_wait(&bcast, &mutex);};
303 
304 
308  inline void signal(void)
309  {pthread_cond_signal(&cond);};
310 
314  inline void broadcast(void)
315  {pthread_cond_broadcast(&bcast);};
316 #endif
317 public:
322 
327 
331  void access(void);
332 
336  void modify(void);
337 
341  void release(void);
342 
346  void commit(void);
347 
354  void limit_sharing(unsigned max);
355 };
356 
365 class __EXPORT TimedEvent : public Timer
366 {
367 private:
368 #ifdef _MSWINDOWS_
369  HANDLE event;
370 #else
371  pthread_cond_t cond;
372  bool signalled;
373 #endif
374  pthread_mutex_t mutex;
375 
376 protected:
381  void lock(void);
382 
387  void release(void);
388 
396  bool sync(void);
397 
398 public:
402  TimedEvent(void);
403 
408  TimedEvent(timeout_t timeout);
409 
414  TimedEvent(time_t timeout);
415 
419  ~TimedEvent();
420 
426  void signal(void);
427 
434  bool wait(timeout_t timeout);
435 
439  void wait(void);
440 
444  void reset(void);
445 
450  inline static void signal(TimedEvent& timed)
451  {timed.signal();};
452 
457  inline static void reset(TimedEvent& timed)
458  {timed.reset();};
459 
466  inline static bool wait(TimedEvent& timed, timeout_t timeout)
467  {return timed.wait(timeout);};
468 };
469 
477 class __EXPORT RecursiveMutex : private Conditional, public ExclusiveProtocol
478 {
479 protected:
480  unsigned waiting;
481  unsigned lockers;
482  pthread_t locker;
483 
484  void Exlock(void);
485  void Unlock(void);
486 
487 public:
491  RecursiveMutex();
492 
496  void lock(void);
497 
501  bool lock(timeout_t timeout);
502 
506  void release(void);
507 
512  unsigned getLocking(void);
513 
518  unsigned getWaiting(void);
519 
524  inline static void lock(RecursiveMutex& rex)
525  {rex.lock();};
526 
531  inline static void release(RecursiveMutex& rex)
532  {rex.release();};
533 };
534 
547 class __EXPORT ThreadLock : private ConditionalAccess, public ExclusiveProtocol, public SharedProtocol
548 {
549 protected:
550  unsigned writers;
551  pthread_t writeid;
552 
553  void Exlock(void);
554  void Shlock(void);
555  void Unlock(void);
556 
557 public:
565  class __EXPORT gaurd_reader
566  {
567  private:
568  void *object;
569 
570  public:
575  gaurd_reader();
576 
581  gaurd_reader(void *object);
582 
586  ~gaurd_reader();
587 
593  void set(void *object);
594 
598  void release(void);
599 
605  inline void operator=(void *pointer)
606  {set(pointer);};
607  };
608 
616  class __EXPORT gaurd_writer
617  {
618  private:
619  void *object;
620 
621  public:
626  gaurd_writer();
627 
632  gaurd_writer(void *object);
633 
637  ~gaurd_writer();
638 
644  void set(void *object);
645 
649  void release(void);
650 
656  inline void operator=(void *pointer)
657  {set(pointer);};
658  };
659 
663  ThreadLock();
664 
670  bool modify(timeout_t timeout = Timer::inf);
671 
677  bool access(timeout_t timeout = Timer::inf);
678 
685  static void indexing(unsigned size);
686 
694  static bool writer(void *object, timeout_t timeout = Timer::inf);
695 
703  static bool reader(void *object, timeout_t timeout = Timer::inf);
704 
709  static void release(void *object);
710 
714  void release(void);
715 
720  unsigned getAccess(void);
721 
726  unsigned getModify(void);
727 
732  unsigned getWaiting(void);
733 
740  inline static bool modify(ThreadLock& lock, timeout_t timeout = Timer::inf)
741  {return lock.modify(timeout);};
742 
749  inline static bool access(ThreadLock& lock, timeout_t timeout = Timer::inf)
750  {return lock.access(timeout);};
751 
756  inline static void release(ThreadLock& lock)
757  {lock.release();};
758 };
759 
770 class __EXPORT ReusableAllocator : protected Conditional
771 {
772 protected:
773  ReusableObject *freelist;
774  unsigned waiting;
775 
780 
786  inline ReusableObject *next(ReusableObject *object)
787  {return object->getNext();};
788 
793  void release(ReusableObject *object);
794 };
795 
806 class __EXPORT ConditionalLock : protected ConditionalAccess, public SharedProtocol
807 {
808 protected:
809  class Context : public LinkedObject
810  {
811  public:
812  inline Context(LinkedObject **root) : LinkedObject(root) {};
813 
814  pthread_t thread;
815  unsigned count;
816  };
817 
818  LinkedObject *contexts;
819 
820  void Shlock(void);
821  void Unlock(void);
822  void Exclusive(void);
823  void Share(void);
824  Context *getContext(void);
825 
826 public:
830  ConditionalLock();
831 
835  ~ConditionalLock();
836 
840  void modify(void);
841 
845  void commit(void);
846 
850  void access(void);
851 
855  void release(void);
856 
861  void exclusive(void);
862 
866  void share(void);
867 
871  unsigned getReaders(void);
872 
876  unsigned getWaiters(void);
877 
882  inline static void modify(ConditionalLock& lock)
883  {lock.modify();};
884 
889  inline static void commit(ConditionalLock& lock)
890  {lock.commit();};
891 
896  inline static void release(ConditionalLock& lock)
897  {lock.release();};
898 
903  inline static void access(ConditionalLock& lock)
904  {lock.access();};
905 
910  inline static void exclusive(ConditionalLock& lock)
911  {lock.exclusive();};
912 
917  inline static void share(ConditionalLock& lock)
918  {lock.share();};
919 };
920 
933 class __EXPORT barrier : private Conditional
934 {
935 private:
936  unsigned count;
937  unsigned waits;
938 
939 public:
944  barrier(unsigned count);
945 
949  ~barrier();
950 
956  void set(unsigned count);
957 
961  void inc(void);
962 
966  void dec(void);
967 
972  unsigned operator++(void);
973 
974  unsigned operator--(void);
975 
979  void wait(void);
980 
987  bool wait(timeout_t timeout);
988 
993  inline static void wait(barrier& sync)
994  {sync.wait();};
995 
1002  inline static bool wait(barrier& sync, timeout_t timeout)
1003  {return sync.wait(timeout);};
1004 
1005 
1011  inline static void set(barrier& sync, unsigned count)
1012  {sync.set(count);};
1013 };
1014 
1023 class __EXPORT Semaphore : public SharedProtocol, protected Conditional
1024 {
1025 protected:
1026  unsigned count, waits, used;
1027 
1028  void Shlock(void);
1029  void Unlock(void);
1030 
1031 public:
1035  Semaphore(unsigned count = 0);
1036 
1041  void wait(void);
1042 
1050  bool wait(timeout_t timeout);
1051 
1056  unsigned getCount(void);
1057 
1062  unsigned getUsed(void);
1063 
1068  void set(unsigned count);
1069 
1073  void release(void);
1074 
1078  inline void operator++(void)
1079  {wait();};
1080 
1084  inline void operator--(void)
1085  {release();};
1086 
1091  inline static void wait(Semaphore& sync)
1092  {sync.wait();};
1093 
1100  inline static bool wait(Semaphore& sync, timeout_t timeout)
1101  {return sync.wait(timeout);};
1102 
1107  inline static void release(Semaphore& sync)
1108  {sync.release();};
1109 };
1110 
1124 class __EXPORT Mutex : public ExclusiveProtocol
1125 {
1126 protected:
1127  pthread_mutex_t mlock;
1128 
1129  void Exlock(void);
1130  void Unlock(void);
1131 
1132 public:
1140  class __EXPORT gaurd
1141  {
1142  private:
1143  void *object;
1144 
1145  public:
1150  gaurd();
1151 
1156  gaurd(void *object);
1157 
1161  ~gaurd();
1162 
1168  void set(void *object);
1169 
1173  void release(void);
1174 
1180  inline void operator=(void *pointer)
1181  {set(pointer);};
1182  };
1183 
1184 
1188  Mutex();
1189 
1193  ~Mutex();
1194 
1198  inline void acquire(void)
1199  {pthread_mutex_lock(&mlock);};
1200 
1204  inline void lock(void)
1205  {pthread_mutex_lock(&mlock);};
1206 
1210  inline void unlock(void)
1211  {pthread_mutex_unlock(&mlock);};
1212 
1216  inline void release(void)
1217  {pthread_mutex_unlock(&mlock);};
1218 
1223  inline static void acquire(Mutex& lock)
1224  {pthread_mutex_lock(&lock.mlock);};
1225 
1230  inline static void lock(Mutex& lock)
1231  {pthread_mutex_lock(&lock.mlock);};
1232 
1237  inline static void unlock(Mutex& lock)
1238  {pthread_mutex_unlock(&lock.mlock);};
1239 
1244  inline static void release(Mutex& lock)
1245  {pthread_mutex_unlock(&lock.mlock);};
1246 
1251  inline static void acquire(pthread_mutex_t *lock)
1252  {pthread_mutex_lock(lock);};
1253 
1258  inline static void lock(pthread_mutex_t *lock)
1259  {pthread_mutex_lock(lock);};
1260 
1265  inline static void unlock(pthread_mutex_t *lock)
1266  {pthread_mutex_unlock(lock);};
1267 
1272  inline static void release(pthread_mutex_t *lock)
1273  {pthread_mutex_unlock(lock);};
1274 
1281  static void indexing(unsigned size);
1282 
1288  static void protect(void *pointer);
1289 
1294  static void release(void *pointer);
1295 };
1296 
1305 class __EXPORT auto_protect
1306 {
1307 private:
1308  // cannot copy...
1309  inline auto_protect(const auto_object &pointer) {};
1310 
1311 protected:
1312  void *object;
1313 
1314  auto_protect();
1315 
1316 public:
1321  auto_protect(void *object);
1322 
1327  ~auto_protect();
1328 
1332  void release(void);
1333 
1338  inline bool operator!() const
1339  {return object == NULL;};
1340 
1345  inline operator bool() const
1346  {return object != NULL;};
1347 
1354  void operator=(void *object);
1355 };
1356 
1368 class __EXPORT LockedPointer
1369 {
1370 private:
1371  friend class locked_release;
1372  pthread_mutex_t mutex;
1374 
1375 protected:
1379  LockedPointer();
1380 
1385  void replace(ObjectProtocol *object);
1386 
1391  ObjectProtocol *dup(void);
1392 
1397  inline void operator=(ObjectProtocol *object)
1398  {replace(object);};
1399 };
1400 
1409 class __EXPORT SharedObject
1410 {
1411 protected:
1412  friend class SharedPointer;
1413 
1422  virtual void commit(SharedPointer *pointer);
1423 
1424 public:
1428  virtual ~SharedObject();
1429 };
1430 
1441 class __EXPORT SharedPointer : protected ConditionalAccess
1442 {
1443 private:
1444  friend class shared_release;
1446 
1447 protected:
1451  SharedPointer();
1452 
1456  ~SharedPointer();
1457 
1464  void replace(SharedObject *object);
1465 
1472  SharedObject *share(void);
1473 };
1474 
1485 class __EXPORT Thread
1486 {
1487 protected:
1488 // may be used in future if we need cancelable threads...
1489 #ifdef _MSWINDOWS_
1490  HANDLE cancellor;
1491 #else
1492  void *cancellor;
1493 #endif
1494 
1495  enum {} reserved; // cancel mode?
1496  pthread_t tid;
1497  size_t stack;
1498  int priority;
1499 
1505  Thread(size_t stack = 0);
1506 
1511  void map(void);
1512 
1513 public:
1520  void setPriority(void);
1521 
1526  static void yield(void);
1527 
1532  static void sleep(timeout_t timeout);
1533 
1540  static Thread *get(void);
1541 
1545  virtual void run(void) = 0;
1546 
1550  virtual ~Thread();
1551 
1560  virtual void exit(void);
1561 
1565  static void init(void);
1566 
1572  static void policy(int polid);
1573 
1578  static void concurrency(int level);
1579 
1586  static bool equal(pthread_t thread1, pthread_t thread2);
1587 
1592  static pthread_t self(void);
1593 
1597  virtual bool isRunning(void);
1598 
1599  inline operator bool()
1600  {return isRunning();}
1601 };
1602 
1613 class __EXPORT JoinableThread : protected Thread
1614 {
1615 protected:
1616 #ifdef _MSWINDOWS_
1617  HANDLE running;
1618 #else
1619  volatile bool running;
1620 #endif
1621  volatile bool joining;
1622 
1627  JoinableThread(size_t size = 0);
1628 
1633  virtual ~JoinableThread();
1634 
1640  void join(void);
1641 
1642 public:
1643  bool isRunning(void);
1644 
1653  void start(int priority = 0);
1654 
1659  inline void background(void)
1660  {start(-1);};
1661 };
1662 
1670 class __EXPORT DetachedThread : protected Thread
1671 {
1672 protected:
1673  bool active;
1674 
1679  DetachedThread(size_t size = 0);
1680 
1686  ~DetachedThread();
1687 
1696  void exit(void);
1697 
1698 public:
1705  void start(int priority = 0);
1706 
1707  bool isRunning(void);
1708 };
1709 
1718 class __EXPORT locked_release
1719 {
1720 protected:
1726  locked_release();
1727 
1733  locked_release(const locked_release &object);
1734 
1735 public:
1742 
1747  ~locked_release();
1748 
1752  void release(void);
1753 
1759  locked_release &operator=(LockedPointer &pointer);
1760 };
1761 
1771 class __EXPORT shared_release
1772 {
1773 protected:
1779  shared_release();
1780 
1786  shared_release(const shared_release &object);
1787 
1788 public:
1794 
1800  ~shared_release();
1801 
1805  void release(void);
1806 
1811  SharedObject *get(void);
1812 
1818  shared_release &operator=(SharedPointer &pointer);
1819 };
1820 
1828 template<class T>
1830 {
1831 public:
1836 
1844  inline const T *dup(void)
1845  {return static_cast<const T*>(SharedPointer::share());};
1846 
1853  inline void replace(T *object)
1854  {SharedPointer::replace(object);};
1855 
1860  inline void operator=(T *object)
1861  {replace(object);};
1862 
1867  inline T *operator*()
1868  {return dup();};
1869 };
1870 
1878 template<class T>
1880 {
1881 public:
1886 
1892  inline T* dup(void)
1893  {return static_cast<T *>(LockedPointer::dup());};
1894 
1899  inline void replace(T *object)
1900  {LockedPointer::replace(object);};
1901 
1906  inline void operator=(T *object)
1907  {replace(object);};
1908 
1914  inline T *operator*()
1915  {return dup();};
1916 };
1917 
1923 template<class T>
1925 {
1926 public:
1931 
1937 
1942  inline T& operator*() const
1943  {return *(static_cast<T *>(object));};
1944 
1949  inline T* operator->() const
1950  {return static_cast<T*>(object);};
1951 
1956  inline T* get(void) const
1957  {return static_cast<T*>(object);};
1958 };
1959 
1965 template<class T>
1967 {
1968 public:
1973 
1980 
1984  inline const T& operator*() const
1985  {return *(static_cast<const T *>(ptr->pointer));};
1986 
1991  inline const T* operator->() const
1992  {return static_cast<const T*>(ptr->pointer);};
1993 
1998  inline const T* get(void) const
1999  {return static_cast<const T*>(ptr->pointer);};
2000 };
2001 
2008 template <class T>
2010 {
2011 public:
2015  inline mutex_pointer() : auto_protect() {};
2016 
2021  inline mutex_pointer(T* object) : auto_protect(object) {};
2022 
2027  inline T& operator*() const
2028  {return *(static_cast<T*>(auto_protect::object));};
2029 
2034  inline T* operator->() const
2035  {return static_cast<T*>(auto_protect::object);};
2036 
2041  inline T* get(void) const
2042  {return static_cast<T*>(auto_protect::object);};
2043 };
2044 
2050 inline void start(JoinableThread *thread, int priority = 0)
2051  {thread->start(priority);}
2052 
2058 inline void start(DetachedThread *thread, int priority = 0)
2059  {thread->start(priority);}
2060 
2065 
2070 
2075 
2079 typedef Mutex mutex_t;
2080 
2085 
2090 
2095 
2100 
2105 inline void wait(barrier_t &barrier)
2106  {barrier.wait();}
2107 
2113 inline void wait(semaphore_t &semaphore, timeout_t timeout = Timer::inf)
2114  {semaphore.wait(timeout);}
2115 
2120 inline void release(semaphore_t &semaphore)
2121  {semaphore.release();}
2122 
2127 inline void acquire(mutex_t &mutex)
2128  {mutex.lock();}
2129 
2134 inline void release(mutex_t &mutex)
2135  {mutex.release();}
2136 
2141 inline void modify(accesslock_t &lock)
2142  {lock.modify();}
2143 
2148 inline void access(accesslock_t &lock)
2149  {lock.access();}
2150 
2156  {lock.release();}
2157 
2163 inline void commit(accesslock_t &lock)
2164  {lock.commit();}
2165 
2171  {lock.exclusive();}
2172 
2177 inline void share(condlock_t &lock)
2178  {lock.share();}
2179 
2184 inline void modify(condlock_t &lock)
2185  {lock.modify();}
2186 
2192 inline void commit(condlock_t &lock)
2193  {lock.commit();}
2194 
2199 inline void access(condlock_t &lock)
2200  {lock.access();}
2201 
2206 inline void release(condlock_t &lock)
2207  {lock.release();}
2208 
2214 inline bool exclusive(rwlock_t &lock, timeout_t timeout = Timer::inf)
2215  {return lock.modify(timeout);}
2216 
2222 inline bool share(rwlock_t &lock, timeout_t timeout = Timer::inf)
2223  {return lock.access(timeout);}
2224 
2229 inline void release(rwlock_t &lock)
2230  {lock.release();}
2231 
2236 inline void lock(rexlock_t &lock)
2237  {lock.lock();}
2238 
2243 inline void release(rexlock_t &lock)
2244  {lock.release();}
2245 
2246 END_NAMESPACE
2247 
2248 #define ENTER_EXCLUSIVE \
2249  do { static pthread_mutex_t __sync__ = PTHREAD_MUTEX_INITIALIZER; \
2250  pthread_mutex_lock(&__sync__);
2251 
2252 #define LEAVE_EXCLUSIVE \
2253  pthread_mutex_unlock(&__sync__);} while(0);
2254 
2255 #endif