164 lines
4.6 KiB
C++

/*
* MSThreads.hh
*
* Copyright 2002, LifeLine Networks BV (www.lifeline.nl). All rights reserved.
* Copyright 2002, Bastiaan Bakker. All rights reserved.
*
* See the COPYING file for the terms of usage and distribution.
*/
#ifndef _LOG4CPP_THREADING_MSTHREADS_HH
#define _LOG4CPP_THREADING_MSTHREADS_HH
#include <string>
// deal with ERROR #define
// N.B. This #includes windows.h with NOGDI and WIN32_LEAN_AND_MEAN #defined.
// If this is not what the user wants, #include windows.h before this file.
#ifndef _WINDOWS_
# ifndef NOGDI
# define NOGDI // this will circumvent the ERROR #define in windows.h
# define LOG4CPP_UNDEFINE_NOGDI
# endif
# ifndef WIN32_LEAN_AND_MEAN
# define WIN32_LEAN_AND_MEAN
# define LOG4CPP_UNDEFINE_WIN32_LEAN_AND_MEAN
# endif
# include <windows.h>
# ifdef LOG4CPP_UNDEFINE_NOGDI
# undef NOGDI
# endif
# ifdef LOG4CPP_UNDEFINE_WIN32_LEAN_AND_MEAN
# undef WIN32_LEAN_AND_MEAN
# endif
#endif // done dealing with ERROR #define
LOG4CPP_NS_BEGIN
namespace threading {
/**
* Return an identifier for the current thread. What these
* identifiers look like is completely up to the underlying
* thread library.
**/
std::string getThreadId();
/**
* A simple object wrapper around CreateMutex() and DeleteMutex()
*/
class LOG4CPP_EXPORT MSMutex {
public:
MSMutex() { InitializeCriticalSection(&_criticalSection); }
~MSMutex() { DeleteCriticalSection(&_criticalSection); }
inline LPCRITICAL_SECTION getCriticalSection() {
return &_criticalSection;
}
private:
MSMutex(const MSMutex& other);
CRITICAL_SECTION _criticalSection;
};
/**
* A simple, non recursive Mutex.
**/
typedef MSMutex Mutex;
/**
* A simple object wrapper around WaitForSingleObject() and
* ReleaseMutex()
*/
class MSScopedLock {
public:
MSScopedLock(MSMutex& mutex) {
_criticalSection = mutex.getCriticalSection();
EnterCriticalSection(_criticalSection);
}
~MSScopedLock() { LeaveCriticalSection(_criticalSection); }
private:
MSScopedLock(const MSScopedLock& other);
LPCRITICAL_SECTION _criticalSection;
};
/**
* A simple "resource acquisition is initialization" idiom type lock
* for Mutex.
**/
typedef MSScopedLock ScopedLock;
/**
* This class holds Thread local data of type T, i.e. for each
* thread a ThreadLocalDataHolder holds 0 or 1 instance of T.
* The held object must be heap allocated and will be deleted
* upon termination of the thread to which it belongs.
**/
template<typename T> class ThreadLocalDataHolder {
public:
inline ThreadLocalDataHolder() :
_key(TlsAlloc()) {};
inline ~ThreadLocalDataHolder() {
TlsFree(_key);
};
/**
* Obtains the Object held for the current thread.
* @return a pointer to the held Object or NULL if no
* Object has been set for the current thread.
**/
inline T* get() const {
return (T*)TlsGetValue(_key);
};
/**
* Obtains the Object held for the current thread.
* Initially each thread holds NULL.
* @return a pointer to the held Object or NULL if no
* Object has been set for the current thread.
**/
inline T* operator->() const { return get(); };
/**
* Obtains the Object held for the current thread.
* @pre get() != NULL
* @return a reference to the held Object.
**/
inline T& operator*() const { return *get(); };
/**
* Releases the Object held for the current thread.
* @post get() == NULL
* @return a pointer to the Object thas was held for
* the current thread or NULL if no Object was held.
**/
inline T* release() {
T* result = (T*)TlsGetValue(_key);
TlsSetValue(_key, NULL);
return result;
};
/**
* Sets a new Object to be held for the current thread. A
* previously set Object will be deleted.
* @param p the new object to hold.
* @post get() == p
**/
inline void reset(T* p = NULL) {
T* thing = (T*)TlsGetValue(_key);
delete thing;
TlsSetValue(_key, p);
};
private:
DWORD _key;
};
}
LOG4CPP_NS_END
#endif