이 포스트의 목적

  • 마이어스 싱글턴(singleton)의 한계를 극복하기 위한 피닉스 싱글턴(phoenix singleton)의 구현방법

이 포스트의 준비물

  • Firefox 4.0 b7
  • g++ 4.3.2
  • vim
  • putty

참조 링크

참조 서적

  • 안드레 알렉산드레스쿠 저. Modern C++ Design. 이기형 역.
    Addiston-Wesley. 인포북. 초판 2003.07.30. page(232 ~ 235)
내용

피닉스 싱글턴(phoenix singleton)이란 무엇인가?

  • 파괴된 메모리가 다시 생성되는 싱글턴을 뜻한다.
  • 마이어스 싱글턴(singleton)의 한계를 극복하는 싱글턴이다.

어떻게 피닉스 싱글턴(phoenix singleton)을 구현하는가?

마이어스 싱글턴을 기반하기 때문에, static 지역 변수를 기반으로 구현된 싱글턴이다. 이 static 지역 변수의 특징은 여러개 있지만, 그 중 메모리 해제 시점 관점에서 본다면, 다음과 같다.

  • 메모리의 생성은 프로그램이 해당 지역변수를 구동 코드를 읽을 때 한다.
  • 프로그램 종료시점에 메모리 파괴가 일어 난다 해도, 그 공간은 빈 공간으로 남아 있는다. (즉, 다른것으로 채워지지 않는다)

이러한 특징 때문에, 프로그램 종료 시점에 그 메모리 공간에 다시 쓰기 위해 위치지정(또는 재배치) new - (원어:placement new)를 사용하며, 파괴 시점을 제어하기 위해 std::atexit 함수을 사용하여 구현한다.

피닉스 싱글턴(phoenix singleton)의 맛보기 코드

이것으로 피닉스 싱글턴(phoenix singleton)을 맛볼 수 있다. 하지만, 피닉스 싱글턴에서 사용하는 std::atexit 문제로 인하여, 완벽하진 못하다. 우선 참조 링크에서 std::atexit 함수가 어떻게 돌아 가는지 확인해 보길 바란다. 이 함수에는 다음과 같은 상황에선 좀 이상하게 작동 할수 있다. 그 상황을 담은 코드는 다음과 같다.

std::atexit 의 문제점

  1. main() 내부에서 atexit(a)를 지정한다.
  2. a() 내부에서 atexit(b) 를 지정한다.

  3. 프로그램 종료 시점이 왔을 때, a 를 호출한다.
  4. a에서 b를 등록한다.

  5. atexit 쓰임 관점에서 본다면, b가 호출되고 a가 호출되어, 프로그램이 종료되어야 하지만 (vc2010 과 g++ 4.3.2 에선 a가 호출되고 b가 호출 되었다.) 보통 a가 호출되고 b가 호출되면서 프로그램이 종료되는 문제가 생긴다.

여기서 말하는 것은, 피닉스 싱글턴(phoenix singleton)을 사용해도, 해결되지 않는 문제가 있고, 이 문제로 싱글턴 소멸시점을 제어할 수 없다. 다시 이러한 문제를 해결하기 위해서, 수명 제어 싱글턴을 구현해 보자.

사실은 이 책이 나올 때, 피닉스 싱글턴(phoenix singleton)에 문제가 발생 했으나, 현 시점에선 호출 순서가 스택 구조가 아닐 순 있어도, 크래쉬는 발생하지 않는다.(크래쉬 발생 여부는 프로그램에서 피닉스 싱글턴을 사용하기 전까진 모르겠다.) 그러므로 사용하는데 지장은 없다. 그래서 수명 제어 싱글턴 구현 포스트는 안하겠다.

다음 포스트에선 "싱글턴이 쓰레드를 만났을 경우 고려사항"을 정리한다.

여담

  • 대부분의 경우, 마이어스 싱글턴으로 해결 가능하다.
  • 마이어스 싱글턴에서 참조 무효화 현상이 일어나면, 피닉스 싱글턴(phoenix singleton)으로 대부분 해결 가능하다.
  • 수명 제어 싱글턴이 쓰이는 경우가 생길까? 라는 의문도 생기지만, 이러한 개념의 존재만 알고 있으면 된다고 생각하기에 패스.

:wq

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 라이프코리아트위터 공유하기
  • shared
  • 카카오스토리 공유하기