http://goo.gl/GZWI4

http://blog.naver.com/ccw3435/100055320847




criticalsectionbase-ccw3435.h


 

//*******************************************************************
//              
//  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 <assert.h>
  
// 스핀 카운트란? 싱글 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 <typename T>
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 <typename T>
CCriticalSectionBase CMultiThreadSync<T>::m_SyncObject;

반응형

+ Recent posts