log4tango  4.0.3
PThreads.hh
Go to the documentation of this file.
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