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