#include<iostream>
#include <stdlib.h>
#include <windows.h>
#include<assert.h>
enum MutexProtocol
{
PrioInherit,
PrioNone
};
//class Cond;
template <typename T>
class LockT
{
public:
LockT(const T& mutex) :_mutex(mutex)
{
_mutex.lock();
_acquired = true;
}
~LockT()
{
if (_acquired)
{
_mutex.unlock();
}
}
void acquire() const
{
if (_acquired)
{
//throw ThreadLockedException(__FILE__, __LINE__);
}
_mutex.lock();
_acquired = true;
}
bool tryAcquire() const
{
if (_acquired)
{
//throw ThreadLockedException(__FILE__, __LINE__);
}
_acquired = _mutex.tryLock();
return _acquired;
}
void release() const
{
if (!_acquired)
{
//throw ThreadLockedException(__FILE__, __LINE__);
}
_mutex.unlock();
_acquired = false;
}
bool acquired() const
{
return _acquired;
}
protected:
// TryLockT's contructor
LockT(const T& mutex, bool) :
_mutex(mutex)
{
_acquired = _mutex.tryLock();
}
private:
// Not implemented; prevents accidental use.
//
LockT(const LockT&);
LockT& operator=(const LockT&);
const T& _mutex;
mutable bool _acquired;
//friend class Cond;
};
template <typename T>
class TryLockT : public LockT<T>
{
public:
TryLockT(const T& mutex) :
LockT<T>(mutex, true)
{}
};
class Mutex
{
public:
typedef LockT<Mutex> Lock;
typedef TryLockT<Mutex> TryLock;
inline Mutex();
inline Mutex(MutexProtocol);
~Mutex();
//
// Note that lock/tryLock & unlock in general should not be used
// directly. Instead use Lock & TryLock.
//
void lock() const;
//
// Returns true if the lock was acquired, and false otherwise.
//
bool tryLock() const;
void unlock() const;
//
// Returns true if the mutex will unlock when calling unlock()
// (false otherwise). For non-recursive mutexes, this will always
// return true.
// This function is used by the Monitor implementation to know whether
// the Mutex has been locked for the first time, or unlocked for the
// last time (that is another thread is able to acquire the mutex).
// Pre-condition: the mutex must be locked.
//
bool willUnlock() const;
private:
inline void init(MutexProtocol);
// noncopyable
Mutex(const Mutex&);
void operator=(const Mutex&);
//
// LockState and the lock/unlock variations are for use by the
// Condition variable implementation.
//
struct LockState
{
# ifdef ICE_HAS_WIN32_CONDVAR
CRITICAL_SECTION* mutex;
# endif
};
void unlock(LockState&) const;
void lock(LockState&) const;
//friend class Cond;
mutable CRITICAL_SECTION _mutex;
};
//
// For performance reasons the following functions are inlined.
//
inline Mutex::Mutex()
{
init(PrioNone);
}
inline Mutex::Mutex(MutexProtocol)
{
init(PrioNone);
}
inline void Mutex::init(MutexProtocol)
{
InitializeCriticalSection(&_mutex);
}
inline Mutex::~Mutex()
{
DeleteCriticalSection(&_mutex);
}
inline void Mutex::lock() const
{
EnterCriticalSection(&_mutex);
assert(_mutex.RecursionCount == 1);
}
inline bool Mutex::tryLock() const
{
if (!TryEnterCriticalSection(&_mutex))
{
return false;
}
if (_mutex.RecursionCount > 1)
{
LeaveCriticalSection(&_mutex);
//throw ThreadLockedException(__FILE__, __LINE__);
}
return true;
}
inline void Mutex::unlock() const
{
assert(_mutex.RecursionCount == 1);
LeaveCriticalSection(&_mutex);
}
inline void Mutex::unlock(LockState&) const
{
LeaveCriticalSection(&_mutex);
}
inline void Mutex::lock(LockState&) const
{
EnterCriticalSection(&_mutex);
}
inline bool Mutex::willUnlock() const
{
return true;
}
void test()
{
Mutex _mutex;
Mutex::Lock sync(_mutex);
}
int main()
{
test();
getchar();
return 0;
}