00001 /* 00002 * PThreads.hh 00003 * 00004 * Copyright 2002, Emiliano Martin emilianomc@terra.es All rights reserved. 00005 * 00006 * See the COPYING file for the terms of usage and distribution. 00007 */ 00008 00009 #ifndef _LOG4CPP_THREADING_PTHREADS_HH 00010 #define _LOG4CPP_THREADING_PTHREADS_HH 00011 00012 #include <log4cpp/Portability.hh> 00013 #include <stdio.h> 00014 #include <pthread.h> 00015 #include <string> 00016 #include <assert.h> 00017 00018 LOG4CPP_NS_BEGIN 00019 namespace threading { 00020 00024 std::string getThreadId(); 00025 00028 #if defined(VXWORKS) 00029 class Mutex { 00030 private: 00031 SEM_ID m_sem; 00032 00033 public: 00034 inline Mutex() { 00035 m_sem = semMCreate( SEM_Q_PRIORITY | SEM_INVERSION_SAFE ); 00036 } 00037 00038 inline void lock() { 00039 STATUS result = semTake( m_sem, WAIT_FOREVER ); 00040 if (result != OK) { 00041 // throw here? 00042 } 00043 } 00044 00045 inline void unlock() { 00046 semGive( m_sem ); 00047 } 00048 00049 inline ~Mutex() { 00050 semDelete( m_sem ); 00051 } 00052 00053 private: 00054 Mutex(const Mutex& m); 00055 Mutex& operator=(const Mutex &m); 00056 }; 00057 #else 00058 class Mutex { 00059 private: 00060 pthread_mutexattr_t mutexattr; 00061 pthread_mutex_t mutex; 00062 00063 public: 00064 inline Mutex() { 00065 ::pthread_mutexattr_init(&mutexattr); 00066 ::pthread_mutexattr_settype(&mutexattr, PTHREAD_MUTEX_RECURSIVE); 00067 ::pthread_mutex_init(&mutex, &mutexattr); 00068 } 00069 00070 inline void lock() { 00071 ::pthread_mutex_lock(&mutex); 00072 } 00073 00074 inline void unlock() { 00075 ::pthread_mutex_unlock(&mutex); 00076 } 00077 00078 inline ~Mutex() { 00079 ::pthread_mutex_destroy(&mutex); 00080 ::pthread_mutexattr_destroy(&mutexattr); 00081 } 00082 00083 private: 00084 Mutex(const Mutex& m); 00085 Mutex& operator=(const Mutex &m); 00086 }; 00087 #endif 00088 00092 class ScopedLock { 00093 private: 00094 Mutex& _mutex; 00095 00096 public: 00097 inline ScopedLock(Mutex& mutex) : 00098 _mutex(mutex) { 00099 _mutex.lock(); 00100 } 00101 00102 inline ~ScopedLock() { 00103 _mutex.unlock(); 00104 } 00105 }; 00106 00110 template<typename T> class ThreadLocalDataHolder { 00111 private: 00112 pthread_key_t _key; 00113 00114 public: 00115 typedef T data_type; 00116 00117 inline ThreadLocalDataHolder() { 00118 ::pthread_key_create(&_key, freeHolder); 00119 } 00120 00121 inline static void freeHolder(void *p) { 00122 assert(p != NULL); 00123 delete reinterpret_cast<T *>(p); 00124 } 00125 00126 inline ~ThreadLocalDataHolder() { 00127 T *data = get(); 00128 if (data != NULL) { 00129 delete data; 00130 } 00131 ::pthread_key_delete(_key); 00132 } 00133 00134 inline T* get() const { 00135 return reinterpret_cast<T *>(::pthread_getspecific(_key)); 00136 } 00137 00138 inline T* operator->() const { return get(); } 00139 inline T& operator*() const { return *get(); } 00140 00141 inline T* release() { 00142 T* result = get(); 00143 ::pthread_setspecific(_key, NULL); 00144 00145 return result; 00146 } 00147 00148 inline void reset(T* p = NULL) { 00149 T *data = get(); 00150 if (data != NULL) { 00151 delete data; 00152 } 00153 ::pthread_setspecific(_key, p); 00154 } 00155 }; 00156 00157 } 00158 LOG4CPP_NS_END 00159 #endif