2008년 11월 19일 수요일

Singleton

아래와 같은 Meyers 아저씨의 싱글톤을 별 문제없이 사용 중 싱글톤 소멸에 관련한 에러 발생.
DXUT 구조에서 OnCreateDevice()에서 처음으로 접근(생성) 하고 OnDestroyDevice() 에서 다시 접근시
이미 싱글톤객체가 소멸되어 있음.

template
class Singleton
{
public:
static T* Instance()
{
if (!ms_pkInstance)
CreateInstance();
return ms_pkInstance;
}

static void CreateInstance()
{
static T kInstance;
ms_pkInstance = &kInstance;
}

private:
static T* ms_pkInstance;
};


template
T* Singleton::ms_pkInstance = 0;

해결방안..

모던 C++에서 소개한 방법 중 불사조 싱글톤의 구현
destroyed_ 변수를 추가하여 소멸되었는지를 판단 후 소멸되었을 경우 다시 생성
부활한 싱글톤은 atexit() 함수를 사용하여 소멸 예약

atexit() 문제발생 : C++표준의원회에서 고칠거라고는 하지만 WindowsXP/VS2005 에서 문제가 있으므로 일단 아래 방법제시

1.메모리 누수 방치 --;; : 누적되지 않고 프로그램 종료 시에만 발생되므로 OS에서 알아서 회수할 거임.
2.싱글톤 생성 시기 조절 : 프로그램 시작부근에서 CreateInstance()를 호출해주면 오래 살아남음 ;;
3.강제 소멸 : 더 이상 필요 없을 경우 KillPhoenixSingleton()함수로 강제 소멸
4.??

참고자료 : 모던 C++디자인

-> 그 외 싱글톤의 수명제어 및 멀티스레딩에 관련된 부분. 각각의 기능을 템플릿으로 나누어 조합할 수 있게 하는 것 등 소개

template
class PhoenixSingleton
{
public:
static T& Instance()
{
if (!ms_pkInstance)
{
if (destoryed_)
{
// Dead Reference
CreateInstance();
new(ms_pkInstance) T;
#ifdef ATEXIT_FIXED
atexit(KillPhoenixSingleton);
#else
destoryedOnce_ = true;
#endif // ATEXIT_FIXED

destoryed_ = false;
}
else
{
CreateInstance();
}
}
return *ms_pkInstance;

}

static void CreateInstance()
{
static T kInstance;
ms_pkInstance = &kInstance;
}

static void KillPhoenixSingleton()
{
#ifndef ATEXIT_FIXED
if(destoryedOnce_)
#endif // ATEXIT_FIXED
ms_pkInstance->~T();
}
protected:
virtual ~PhoenixSingleton()
{
ms_pkInstance = 0;
destoryed_ = true;
}

static T* ms_pkInstance;
static bool destoryed_;

#ifndef ATEXIT_FIXED
static bool destoryedOnce_;
#endif // ATEXIT_FIXED

};

template
T* PhoenixSingleton::ms_pkInstance = 0;
template
bool PhoenixSingleton::destoryed_ = false;

#ifndef ATEXIT_FIXED
template
bool PhoenixSingleton::destoryedOnce_ = false;
#endif // ATEXIT_FIXED

댓글 없음: