log4tango 4.0.3
|
00001 // 00002 // MSThreads.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_MSTHREADS_H 00029 #define _LOG4TANGO_THREADING_MSTHREADS_H 00030 00031 #include <string> 00032 00033 // deal with ERROR #define 00034 00035 // This #includes windows.h with NOGDI and WIN32_LEAN_AND_MEAN 00036 // #defined. If this is not what the user wants, #include 00037 // windows.h before this file. 00038 00039 #ifndef _WINDOWS_ 00040 # ifndef NOGDI 00041 # define NOGDI // circumvent the ERROR #define in windows.h 00042 # define LOG4TANGO_UNDEFINE_NOGDI 00043 # endif 00044 00045 # ifndef WIN32_LEAN_AND_MEAN 00046 # define WIN32_LEAN_AND_MEAN 00047 # define LOG4TANGO_UNDEFINE_WIN32_LEAN_AND_MEAN 00048 # endif 00049 00050 # include <windows.h> 00051 00052 # ifdef LOG4TANGO_UNDEFINE_NOGDI 00053 # undef NOGDI 00054 # endif 00055 00056 # ifdef LOG4TANGO_UNDEFINE_WIN32_LEAN_AND_MEAN 00057 # undef WIN32_LEAN_AND_MEAN 00058 # endif 00059 00060 #endif 00061 // done dealing with ERROR #define 00062 00063 namespace log4tango { 00064 00065 namespace threading { 00066 00067 std::string get_thread_id (void); 00068 00069 long thread_id (void); 00070 00071 //----------------------------------------------------------------------------- 00072 // Class : MSMutex 00073 //----------------------------------------------------------------------------- 00074 class LOG4TANGO_EXPORT Mutex 00075 { 00076 public: 00077 00078 Mutex() { 00079 InitializeCriticalSection(&_criticalSection); 00080 } 00081 00082 ~Mutex() { 00083 DeleteCriticalSection(&_criticalSection); 00084 } 00085 00086 inline LPCRITICAL_SECTION get_critical_section (void) { 00087 return &_criticalSection; 00088 } 00089 00090 private: 00091 Mutex(const Mutex&); 00092 Mutex operator=(const Mutex&); 00093 00094 CRITICAL_SECTION _criticalSection; 00095 }; 00096 00097 //----------------------------------------------------------------------------- 00098 // Class : ScopedLock 00099 //----------------------------------------------------------------------------- 00100 class ScopedLock 00101 { 00102 public: 00103 00104 ScopedLock (Mutex& mutex) { 00105 _criticalSection = mutex.get_critical_section(); 00106 EnterCriticalSection(_criticalSection); 00107 } 00108 00109 ~ScopedLock() { 00110 LeaveCriticalSection(_criticalSection); 00111 } 00112 00113 private: 00114 ScopedLock(const ScopedLock&); 00115 ScopedLock operator=(const ScopedLock&); 00116 00117 LPCRITICAL_SECTION _criticalSection; 00118 }; 00119 00120 //----------------------------------------------------------------------------- 00121 // Class : RecursiveMutex 00122 //----------------------------------------------------------------------------- 00123 class RecursiveMutex 00124 { 00125 public: 00126 // ctor 00127 RecursiveMutex (void) : recursion_level_(0) { 00128 ::InitializeCriticalSection(&guard_); 00129 } 00130 00131 // dtor 00132 ~RecursiveMutex (void) { 00133 ::DeleteCriticalSection(&guard_); 00134 } 00135 00136 // Locking an RecursiveMutex: 00137 // If <timeout_> is null (the default), <lock> blocks until 00138 // the mutex is acquired and returns 1 (true). Otherwise, 00139 // <lock> blocks until the mutex is acquired or times out 00140 // after <timeout_> milliseconds in which case 0 (false) is 00141 // returned. 00142 inline int lock (long timeout_ = 0) { 00143 ::EnterCriticalSection(&guard_); 00144 recursion_level_++; 00145 return 0; 00146 } 00147 00148 // Releasing an RecursiveMutex: 00149 // Call unlock <recursion level> times (i.e. one call for 00150 // each previous call to lock) or call unlockn just once. 00151 // These two methods do nothing if the caller is not the 00152 // current owner of the mutex. 00153 inline void unlock (void) { 00154 //-should work if called by owner 00155 recursion_level_--; 00156 ::LeaveCriticalSection(&guard_); 00157 } 00158 00159 inline void unlockn (void) { 00160 //-should work if called by owner 00161 while (recursion_level_ > 0) { 00162 recursion_level_--; 00163 ::LeaveCriticalSection(&guard_); 00164 } 00165 } 00166 00167 protected: 00168 // guards the <recursion level> 00169 CRITICAL_SECTION guard_; 00170 00171 private: 00172 // current level of the recursion 00173 unsigned long recursion_level_; 00174 00175 // dummy copy constructor and operator= to prevent copying 00176 RecursiveMutex (const RecursiveMutex&); 00177 RecursiveMutex& operator= (const RecursiveMutex&); 00178 }; 00179 00180 //----------------------------------------------------------------------------- 00181 // Class : ThreadLocalDataHolder 00182 //----------------------------------------------------------------------------- 00189 #ifdef LOG4TANGO_HAS_NDC 00190 template<typename T> class ThreadLocalDataHolder 00191 { 00192 public: 00193 00194 inline ThreadLocalDataHolder() 00195 : _key(TlsAlloc()) { 00196 }; 00197 00198 inline ~ThreadLocalDataHolder() { 00199 TlsFree(_key); 00200 }; 00201 00207 inline T* get (void) const { 00208 return (T*)TlsGetValue(_key); 00209 }; 00210 00217 inline T* operator->() const { 00218 return get(); 00219 }; 00220 00226 inline T& operator*() const { 00227 return *get(); 00228 }; 00229 00236 inline T* release() { 00237 T* result = (T*)TlsGetValue(_key); 00238 TlsSetValue(_key, NULL); 00239 return result; 00240 }; 00241 00248 inline void reset(T* p = NULL) { 00249 T* thing = (T*)TlsGetValue(_key); 00250 delete thing; 00251 TlsSetValue(_key, p); 00252 }; 00253 00254 private: 00255 00256 DWORD _key; 00257 }; 00258 00259 #endif // LOG4TANGO_HAS_NDC 00260 00261 } // namespace threading 00262 00263 } // namespace log4tango 00264 00265 #endif // _LOG4TANGO_THREADING_MSTHREADS_H