project64/Source/Common/CriticalSection.h

106 lines
2.7 KiB
C++

/**
* @file
*/
#pragma once
#include <windows.h>
#include <exception>
#include <string>
/**
* Encapsulates a Win32 critical section.
* Provides control over creation and clean destruction of native win32 critical sections. Also
* allows the object to be used directly in place of a CRITICAL_SECTION handle via the void* overload
*
* @author Peter Hancock
*
*/
class CriticalSection
{
public:
/**
* Create the critical section.
*/
CriticalSection()
{
::InitializeCriticalSection(&cs);
}
/**
* Cleans up the critical section.
*/
~CriticalSection(void)
{
::DeleteCriticalSection(&cs);
}
/**
* Enters a critical section of code.
* Prevents other threads from accessing the section between the enter and leave sections simultaneously.
* @note It is good practice to try and keep the critical section code as little as possible, so that
* other threads are not locked waiting for it.
*/
void enter(void)
{
::EnterCriticalSection(&cs);
}
/**
* Leaves the critical section.
* Allows threads access to the critical code section again.
* @warning Note that an exception occurring with a critical section may not result in the expected leave being
* called. To ensure that your critical section is exception safe, ensure that you wrap the critical
* section in a try catch, and the catch calls the leave method.
*/
void leave(void)
{
::LeaveCriticalSection(&cs);
}
/**
* Provides conversion to the native WIN32 CRITICAL_SECTION object
* Allows the client to use the CriticalSection object as a native handle also.
* @return CRITICAL_SECTION handle
*/
operator CRITICAL_SECTION&()
{
return cs;
}
private:
CriticalSection(const CriticalSection&); // Disable copy constructor
CriticalSection& operator=(const CriticalSection&); // Disable assignment
CRITICAL_SECTION cs;
};
/**
* CGuard class provides exception safety for critical sections
* A helper class that enters a critical section on construction, and leaves
* the critical section on destruction.
*
* @code
int i;
{
CGuard loopGuard(moduleCS); // enters the critical section
for(int i=0 ; i < 10 ; i++)
{
// Do stuff here // If an exception is thrown here, loopGuard goes out of scope - calling leave()
}
} // Guard goes out of scope here, destructor calls leave()
* @endcode
*
* @author Peter Hancock
*
*/
class CGuard
{
public:
CGuard(CriticalSection& sectionName) : cs(sectionName)
{
cs.enter();
}
~CGuard()
{
cs.leave();
}
private:
CriticalSection& cs;
CGuard(const CGuard& copy);
CGuard &operator=(const CGuard& rhs);
};