log4tango
4.0.3
|
00001 // 00002 // PThreads.hh 00003 // 00004 // Copyright (C) : 2000 - 2002 00005 // LifeLine Networks BV (www.lifeline.nl). All rights reserved. 00006 // Bastiaan Bakker. All rights reserved. 00007 // 00008 // 2004,2005,2006,2007,2008,2009,2010 00009 // Synchrotron SOLEIL 00010 // L'Orme des Merisiers 00011 // Saint-Aubin - BP 48 - France 00012 // 00013 // This file is part of log4tango. 00014 // 00015 // Log4ango is free software: you can redistribute it and/or modify 00016 // it under the terms of the GNU Lesser General Public License as published by 00017 // the Free Software Foundation, either version 3 of the License, or 00018 // (at your option) any later version. 00019 // 00020 // Log4tango is distributed in the hope that it will be useful, 00021 // but WITHOUT ANY WARRANTY; without even the implied warranty of 00022 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00023 // GNU Lesser General Public License for more details. 00024 // 00025 // You should have received a copy of the GNU Lesser General Public License 00026 // along with Log4Tango. If not, see <http://www.gnu.org/licenses/>. 00027 00028 #ifndef _LOG4TANGO_THREADING_PTHREADS_H 00029 #define _LOG4TANGO_THREADING_PTHREADS_H 00030 00031 #include <log4tango/Portability.hh> 00032 #include <stdio.h> 00033 #include <pthread.h> 00034 #include <string> 00035 #include <assert.h> 00036 00037 namespace log4tango { 00038 00039 namespace threading { 00040 00041 std::string get_thread_id (void); 00042 00043 long thread_id (void); 00044 00045 //----------------------------------------------------------------------------- 00046 // Class : Mutex 00047 //----------------------------------------------------------------------------- 00048 class Mutex 00049 { 00050 private: 00051 pthread_mutex_t mutex; 00052 00053 00054 public: 00055 inline Mutex() { 00056 ::pthread_mutex_init(&mutex, NULL); 00057 } 00058 00059 inline ~Mutex() { 00060 ::pthread_mutex_destroy(&mutex); 00061 } 00062 00063 inline void lock() { 00064 ::pthread_mutex_lock(&mutex); 00065 } 00066 00067 inline void unlock() { 00068 ::pthread_mutex_unlock(&mutex); 00069 } 00070 }; 00071 00072 //----------------------------------------------------------------------------- 00073 // Class : ScopedLock 00074 //----------------------------------------------------------------------------- 00075 class ScopedLock 00076 { 00077 private: 00078 Mutex& _mutex; 00079 00080 public: 00081 inline ScopedLock(Mutex &m) : _mutex(m) { 00082 _mutex.lock(); 00083 } 00084 00085 inline ~ScopedLock() { 00086 _mutex.unlock(); 00087 } 00088 }; 00089 00090 //----------------------------------------------------------------------------- 00091 // Class : RecursiveMutex 00092 //----------------------------------------------------------------------------- 00093 class RecursiveMutex 00094 { 00095 public: 00096 // ctor 00097 RecursiveMutex (void); 00098 00099 // dtor 00100 ~RecursiveMutex (void); 00101 00102 // Locking an RecursiveMutex: 00103 // If <timeout_> is null (the default), <lock> blocks until 00104 // the mutex is acquired and returns 1 (true). Otherwise, 00105 // <lock> blocks until the mutex is acquired or times out 00106 // after <timeout_> milliseconds in which case 0 (false) is 00107 // returned. 00108 int lock (long timeout_ = 0); 00109 00110 // Releasing an RecursiveMutex: 00111 // Call unlock <recursion level> times (i.e. one call for 00112 // each previous call to lock) or call unlockn just once. 00113 // These two methods do nothing if the caller is not the 00114 // current owner of the mutex. 00115 void unlock (void); 00116 void unlockn (void); 00117 00118 protected: 00119 // guards the <recursion level> and <owner id> 00120 pthread_mutex_t guard_; 00121 00122 // this condition variable suspends other waiting threads 00123 // until the mutex is available 00124 pthread_cond_t mutex_available_; 00125 00126 private: 00127 // current level of the recursion 00128 long recursion_level_; 00129 00130 // current owner of the lock. 00131 pthread_t owner_id_; 00132 00133 // dummy copy constructor and operator= to prevent copying 00134 RecursiveMutex (const RecursiveMutex&); 00135 RecursiveMutex& operator= (const RecursiveMutex&); 00136 }; 00137 00138 //----------------------------------------------------------------------------- 00139 // Class : ThreadLocalDataHolder 00140 //----------------------------------------------------------------------------- 00141 #ifdef LOG4TANGO_HAS_NDC 00142 template<typename T> class ThreadLocalDataHolder { 00143 00144 private: 00145 pthread_key_t _key; 00146 00147 public: 00148 typedef T data_type; 00149 00150 inline ThreadLocalDataHolder() { 00151 ::pthread_key_create(&_key, freeHolder); 00152 } 00153 00154 inline static void freeHolder(void *p) { 00155 assert(p != NULL); 00156 delete reinterpret_cast<T *>(p); 00157 } 00158 00159 inline ~ThreadLocalDataHolder() { 00160 T *data = get(); 00161 if (data != NULL) { 00162 delete data; 00163 } 00164 ::pthread_key_delete(_key); 00165 } 00166 00167 inline T* get() const { 00168 return reinterpret_cast<T *>(::pthread_getspecific(_key)); 00169 } 00170 00171 inline T* operator->() const { return get(); } 00172 inline T& operator*() const { return *get(); } 00173 00174 inline T* release() { 00175 T* result = get(); 00176 ::pthread_setspecific(_key, NULL); 00177 return result; 00178 } 00179 00180 inline void reset(T* p = NULL) { 00181 T *data = get(); 00182 if (data != NULL) { 00183 delete data; 00184 } 00185 ::pthread_setspecific(_key, p); 00186 } 00187 }; 00188 #endif //LOG4TANGO_HAS_NDC 00189 00190 } // namespace threading 00191 00192 } // namespace log4tango 00193 00194 #endif // _LOG4TANGO_THREADING_PTHREADS_H