167 lines
4.8 KiB
C++
167 lines
4.8 KiB
C++
#pragma once
|
|
// winmutex.h
|
|
// 12/11/2011 jichi
|
|
|
|
#include <windows.h>
|
|
|
|
#ifdef _MSC_VER
|
|
# pragma warning(disable:4800) // C4800: forcing value to bool
|
|
#endif // _MSC_VER
|
|
|
|
// Mutex lock
|
|
// The interface of this class is consistent with the mutex class
|
|
|
|
template <typename _Mutex>
|
|
class win_mutex_lock
|
|
{
|
|
typedef win_mutex_lock<_Mutex> _Self;
|
|
win_mutex_lock(const _Self&);
|
|
_Self &operator=(const _Self&);
|
|
|
|
_Mutex &_M_mutex;
|
|
bool _M_locked;
|
|
public:
|
|
typedef _Mutex mutex_type;
|
|
typedef typename _Mutex::native_handle_type native_handle_type;
|
|
explicit win_mutex_lock(mutex_type &mutex)
|
|
: _M_mutex(mutex), _M_locked(false) { lock(); }
|
|
~win_mutex_lock() { if (_M_locked) _M_mutex.unlock(); }
|
|
mutex_type &mutex() { return _M_mutex; }
|
|
//bool isLock() const { return _M_locked; }
|
|
native_handle_type native_handle() { return _M_mutex.native_handle(); }
|
|
void unlock() { _M_mutex.unlock(); _M_locked = false; }
|
|
void lock() { _M_mutex.lock(); _M_locked = true; }
|
|
bool tryLock() { return _M_locked = _M_mutex.tryLock(); }
|
|
};
|
|
|
|
// Mutex
|
|
|
|
template <typename _Mutex, size_t _Irql = 0>
|
|
class win_mutex
|
|
{
|
|
typedef win_mutex<_Mutex> _Self;
|
|
typedef _Mutex __native_type;
|
|
enum { __minimal_irql = _Irql };
|
|
__native_type _M_mutex;
|
|
|
|
win_mutex(const _Self&);
|
|
_Self &operator=(const _Self&);
|
|
private:
|
|
win_mutex() {}
|
|
typedef __native_type *native_handle_type;
|
|
native_handle_type native_handle() { return &_M_mutex; }
|
|
static size_t minimal_irql() { return __minimal_irql; }
|
|
|
|
void unlock() {}
|
|
void lock() {}
|
|
bool try_lock() {}
|
|
};
|
|
|
|
template <>
|
|
class IHFSERVICE win_mutex<CRITICAL_SECTION>
|
|
{
|
|
typedef win_mutex<CRITICAL_SECTION> _Self;
|
|
typedef CRITICAL_SECTION __native_type;
|
|
enum { __minimal_irql = 0 };
|
|
win_mutex(const _Self&);
|
|
_Self &operator=(const _Self&);
|
|
|
|
__native_type _M_mutex;
|
|
public:
|
|
typedef __native_type *native_handle_type;
|
|
native_handle_type native_handle() { return &_M_mutex; }
|
|
static size_t minimal_irql() { return __minimal_irql; }
|
|
|
|
win_mutex() { ::InitializeCriticalSection(&_M_mutex); }
|
|
~win_mutex() { ::DeleteCriticalSection(&_M_mutex); }
|
|
void lock() { ::EnterCriticalSection(&_M_mutex); }
|
|
void unlock() { ::LeaveCriticalSection(&_M_mutex); }
|
|
bool try_lock() { return ::TryEnterCriticalSection(&_M_mutex); }
|
|
};
|
|
|
|
// Conditional variable
|
|
|
|
template <typename _Cond>
|
|
class win_mutex_cond
|
|
{
|
|
typedef win_mutex_cond<_Cond> _Self;
|
|
typedef _Cond __native_type;
|
|
win_mutex_cond(const _Self&);
|
|
_Self &operator=(const _Self&);
|
|
|
|
__native_type _M_cond;
|
|
public:
|
|
enum wait_status { no_timeout = 0, timeout };
|
|
typedef __native_type *native_handle_type;
|
|
|
|
win_mutex_cond() {}
|
|
native_handle_type native_handle() { return &_M_cond; }
|
|
|
|
void notify_one() {}
|
|
void notify_all() {}
|
|
|
|
template <typename _Mutex>
|
|
void wait(_Mutex &mutex) {}
|
|
|
|
template <typename _Mutex, typename _Pred>
|
|
void wait(_Mutex &mutex, _Pred pred) {}
|
|
|
|
template <typename _Mutex>
|
|
wait_status wait_for(_Mutex &mutex, int msecs) {}
|
|
|
|
template <typename _Mutex, typename _Pred>
|
|
wait_status wait_for(_Mutex &mutex, int msecs, _Pred pred) {}
|
|
};
|
|
|
|
// Note: Conditional variables are NOT availabe on Windows XP/2003
|
|
// See: http://en.cppreference.com/w/cpp/thread/condition_variable
|
|
// See: http://msdn.microsoft.com/en-us/library/windows/desktop/ms686903%28v=vs.85%29.aspx
|
|
template <>
|
|
class win_mutex_cond<CONDITION_VARIABLE>
|
|
{
|
|
typedef win_mutex_cond<CONDITION_VARIABLE> _Self;
|
|
typedef CONDITION_VARIABLE __native_type;
|
|
win_mutex_cond(const _Self&);
|
|
_Self &operator=(const _Self&);
|
|
|
|
__native_type _M_cond;
|
|
public:
|
|
enum wait_status { no_timeout = 0, timeout };
|
|
typedef __native_type *native_handle_type;
|
|
native_handle_type native_handle() { return &_M_cond; }
|
|
|
|
win_mutex_cond() { ::InitializeConditionVariable(&_M_cond); }
|
|
|
|
void notify_one() { ::WakeConditionVariable(&_M_cond); }
|
|
void notify_all() { ::WakeAllConditionVariable(&_M_cond); }
|
|
|
|
template <typename _Mutex>
|
|
void wait(_Mutex &mutex)
|
|
{ ::SleepConditionVariableCS(&_M_cond, mutex.native_handle(), INFINITE); }
|
|
|
|
template <typename _Mutex, typename _Pred>
|
|
void wait(_Mutex &mutex, _Pred pred)
|
|
{ while (!pred()) wait(mutex); }
|
|
|
|
template <typename _Mutex>
|
|
wait_status wait_for(_Mutex &mutex, int msecs)
|
|
{ return ::SleepConditionVariableCS(&_M_cond, mutex.native_handle(), msecs) ? no_timeout : timeout; }
|
|
|
|
template <typename _Mutex, typename _Pred>
|
|
wait_status wait_for(_Mutex &mutex, int msecs, _Pred pred)
|
|
{
|
|
auto start = ::GetTickCount();
|
|
while (!pred()) {
|
|
auto now = ::GetTickCount();
|
|
msecs -= now - start;
|
|
if (msecs <= 0)
|
|
return timeout;
|
|
start = now;
|
|
wait_for(mutex, msecs);
|
|
}
|
|
return no_timeout;
|
|
}
|
|
};
|
|
|
|
// EOF
|