DragonNest/Server/ServiceMonitorEx/Source/CriticalSection.hpp
2024-12-19 09:48:26 +08:00

275 lines
7.4 KiB
C++

/*//===============================================================
<< CRITICAL SECTION >>
PRGM : milkji, B4nFter
FILE : CRITICALSECTION.HPP
DESC : 자동해제 기능을 가진 확장된 임계구역
INIT BUILT DATE : 2005. 06. 02
LAST BUILT DATE : 2005. 06. 02
P.S.>
- DEBUG 모드 컴파일 : 임계구역 관련 API로 진입/해제 하는것 보다 3배 정도의 성능저하
- RELEASE 모드 컴파일 : 임계구역 관련 API와 거의 성능차이 없음
Copyrightⓒ 2002~2009 B4nFter (b4nfter@gmail.com) and Co-Writers. All Rights Reserved.
*///===============================================================
#pragma once
///////////////////////////////////////////////////////////////////
// INCLUDE
///////////////////////////////////////////////////////////////////
#include "LOCKBASE.HPP"
///////////////////////////////////////////////////////////////////
// DEFINE
///////////////////////////////////////////////////////////////////
///////////////////////////////////////////////////////////////////
// DECLARATION
///////////////////////////////////////////////////////////////////
//*---------------------------------------------------------------
// TYPE : CLASS
// NAME : CCriticalSection
//*---------------------------------------------------------------
// DESC : Critical Section Class
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
class CCriticalSection : public CLockBase
{
private:
DISABLE_COPY_ASSIGN(CCriticalSection) // 객체간 복사, 대입 금지
public:
CCriticalSection();
virtual ~CCriticalSection();
DWORD Open(DWORD dwSpinCount = 0);
VOID Close();
BOOL IsOpen() const;
VOID Lock(BOOL bDoCheck = FALSE) const;
BOOL LockTry() const;
VOID Unlock() const;
#if defined(_DEBUG)
BOOL IsLock() const;
#endif // #if defined(_DEBUG)
private:
VOID Reset();
private:
mutable CRITICAL_SECTION m_crThis;
};
///////////////////////////////////////////////////////////////////
// IMPLEMENTATION
///////////////////////////////////////////////////////////////////
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::CCriticalSection
//*---------------------------------------------------------------
// DESC : 생성자
// PARM : 1 . lpCriticalSection - 생성된 임계구역 객체의 포인터
// RETV : N/A
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline CCriticalSection::CCriticalSection()
{
Reset();
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::~CCriticalSection
//*---------------------------------------------------------------
// DESC : 소멸자
// PARM : N/A
// RETV : N/A
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline CCriticalSection::~CCriticalSection()
{
Close();
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::Open
//*---------------------------------------------------------------
// DESC : 객체 시작, 자원 초기화
// PARM : 1 . dwSpinCount -
// RETV : NOERROR - 성공 / 그외 - 실패
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
#pragma warning(disable:4100)
inline DWORD CCriticalSection::Open(DWORD dwSpinCount)
{
::memset(&m_crThis, '\0', sizeof(m_crThis));
#if ((WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0403))
if (dwSpinCount > 0) {
/*
P.S.>
- 스핀카운트의 최상위 비트를 세트하면 ::EnterCriticalSection() 에 필요한 자원을 미리 할당
- 이것은 상당량의 Non-Paged Pool 을 소비하므로 많은 수의 임계구역 생성 시 꺼야함
- 이것은 오직 Windows Server 2000 에서만 동작함 (XP 이상에서는 제거됨)
*/
// dwSpinCount |= 0x80000000;
if (::InitializeCriticalSectionAndSpinCount(&m_crThis, dwSpinCount)) {
m_bIsOpen = TRUE;
return (NOERROR);
}
}
#endif // #if ((WINVER >= 0x0500) && (_WIN32_WINNT >= 0x0500))
DWORD dwRetVal;
__try {
::InitializeCriticalSection(&m_crThis);
m_bIsOpen = TRUE;
dwRetVal = NOERROR;
}
__except(EXCEPTION_EXECUTE_HANDLER)
{
dwRetVal = STATUS_NO_MEMORY;
}
return dwRetVal;
}
#pragma warning(default:4100)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::Close
//*---------------------------------------------------------------
// DESC : 객체 종료, 자원 해제
// PARM : N/A
// RETV : N/A
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline VOID CCriticalSection::Close()
{
if (m_bIsOpen) {
::DeleteCriticalSection(&m_crThis);
Reset();
}
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::IsOpen
//*---------------------------------------------------------------
// DESC : 현재 객체가 준비되어 있는지 체크
// PARM : N/A
// RETV : TRUE - 맞음 / FALSE - 틀림
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline BOOL CCriticalSection::IsOpen() const
{
return m_bIsOpen;
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::Lock
//*---------------------------------------------------------------
// DESC : 임계구역 진입
// PARM : 1 . bDoCheck -
// RETV : N/A
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
#pragma warning(disable:4100)
inline VOID CCriticalSection::Lock(BOOL bDoCheck) const
{
::EnterCriticalSection(&m_crThis);
}
#pragma warning(default:4100)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::LockTry
//*---------------------------------------------------------------
// DESC : 임계구역 진입 시도
// PARM : N/A
// RETV : TRUE - 성공 / FALSE - 실패
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline BOOL CCriticalSection::LockTry() const
{
#if (WINVER >= 0x0500)
if (::TryEnterCriticalSection(&m_crThis))
return(TRUE);
else
return(FALSE);
#else // #if (WINVER >= 0x0500)
BASE_RETURN(FALSE);
#endif // #if (WINVER >= 0x0500)
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::Unlock
//*---------------------------------------------------------------
// DESC : 임계구역 해제
// PARM : N/A
// RETV : N/A
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline VOID CCriticalSection::Unlock() const
{
::LeaveCriticalSection(&m_crThis);
}
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::IsLock
//*---------------------------------------------------------------
// DESC : 임계구역에 이미 진입해 있는지 체크
// PARM : N/A
// RETV : TRUE - 맞음 / FALSE - 틀림
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
#if defined(_DEBUG)
inline BOOL CCriticalSection::IsLock() const
{
return((0 < m_crThis.RecursionCount) && (::GetCurrentThreadId() == HandleToUlong(m_crThis.OwningThread)));
}
#endif // #if defined(_DEBUG)
//*---------------------------------------------------------------
// TYPE : FUNCTION
// NAME : CCriticalSection::Reset
//*---------------------------------------------------------------
// DESC : 객체 자원 초기화
// PARM : N/A
// RETV : N/A
// PRGM : milkji, B4nFter
//*---------------------------------------------------------------
inline VOID CCriticalSection::Reset()
{
m_bIsOpen = FALSE;
}