//*******************************************************************
//              
//  FILE:       CriticalSectionBase.h
//              
//  AUTHOR:     - TTF(zone0000@dreamwiz.com)
//              
//  PROJECT:    CriticalSection
//              
//  COMPONENT:  CCriticalSectionBase
//              
//  DATE:       16.05.2007
//              
//  COMMENTS:   - v1.0 (2007.05.16)
//				  Spin Count를 적용하여 윈도우 버전에 맞게 자동 선택
//                try/catch문을 이용하여 동기화 객체 할당시 메모리 오류 assert 처리
//              
//*******************************************************************

#pragma once

#include 

// 스핀 카운트란? 싱글 Processor 시스템에서는 무시되는 항목이지만,
// 멀티 Processor 시스템에서 Critical Section을 사용할 수 없을 때
// 세마포어와 연계되어 작동하는데, 세마포어는 커널 모드에서 작동하므로
// 호출되는 스레드가 유저모드에서 대기(busy-waiting) 상태로 남아 있을 경우에
// 더욱 효율적일 수 있다.
// 요약 - 유저모드로 대기하는 스레드의 갯수에 대한 설정이다.

class CCriticalSectionBase
{
public:
#if (_WIN32_WINNT < 0x0403)
	CCriticalSectionBase()
	{
		__try
		{
			InitializeCriticalSection( &m_CS );
		}
		__except( STATUS_NO_MEMORY == GetExceptionCode() )
		{
			assert( !"Out Of Memory" );
		}
	}
#elif (_WIN32_WINNT >= 0x0403)
	CCriticalSectionBase( ULONG nSpinCount = 4000 )
	{
		// SpinCount의 MS-SQL 기본값 : 4000
		// 윈도우 2000에서는 아무리 많은 스핀 카운트를 쓰려고 하더라도
		// 최상위 비트를 1로 세팅하지 말아야 한다.(MSDN 참조 - XP 이상은 최상위 비트가 무시된다.)
		// nSpinCount = 0x80000400;

		__try
		{
			BOOL bRet = InitializeCriticalSectionAndSpinCount( &m_CS, nSpinCount );
			if( !bRet )
			{
				assert( !"Out Of Memory" );
			}
		}
		__except( STATUS_NO_MEMORY == GetExceptionCode() ) 
		{
			assert( !"Out Of Memory" );
		}
	}
#endif

	~CCriticalSectionBase()
	{
		DeleteCriticalSection( &m_CS );			// Critical Section 개체 삭제
	}

	inline void Enter()
	{
		__try
		{
			EnterCriticalSection( &m_CS );		// Critical Section 진입(Lock)
		}
		__except(STATUS_NO_MEMORY == GetExceptionCode())
		{
			assert( !"Out Of Memory" );
		}
	}

	inline void Leave()
	{
		LeaveCriticalSection( &m_CS );			// Critical Section 해제(UnLock)
	}

#if (_WIN32_WINNT >= 0x0403)
	inline ULONG SetSpinCount( ULONG nSpinCount )
	{
		return( SetCriticalSectionSpinCount( &m_CS, nSpinCount ) );
	}
#endif

#if(_WIN32_WINNT >= 0x0400)
	inline BOOL TryEnter()
	{
		return( TryEnterCriticalSection( &m_CS ) );
	}
#endif

private:
	CRITICAL_SECTION m_CS;						// Critical Section 개체
};


template 
class CMultiThreadSync
{
	friend class CThreadSync;

public:
	class CThreadSync
	{
	public:
		CThreadSync()
		{
			T::m_SyncObject.Enter();
		}

		~CThreadSync()
		{
			T::m_SyncObject.Leave();
		}
	};

private:
	static CCriticalSectionBase m_SyncObject;
};

template 
CCriticalSectionBase CMultiThreadSync::m_SyncObject;
2007/05/16 03:40 2007/05/16 03:40

덧글을 달아 주세요