템플릿으로 싱글톤 클래스를 만드려고 합니다.

Macuro의 이미지

template <typename T> class Singleton
{
private:
	//Singleton(){};
	//virtual ~Singleton(){};
	static T* m_pThis;
public:
 
	static T* getPointer()
	{
		if(m_pThis == NULL)
		{
			m_pThis = new T[1];
		}
		return m_pThis;
	}
 
static T* Release()
	{
		if(m_pThis != NULL)
			delete []m_pThis;
		m_pThis = NULL;
	}
};
 
template <typename T> T* Singleton <T>::m_pThis = NULL;

이렇게 되있는데 여기서 private에 생성자,소멸자가 있으면 상속 받았을때
오류error C2248: 'Singleton::Singleton' : private 멤버('Singleton' 클래스에서 선언)에 액세스할 수 없습니다.
이런 에러가 뜨는데 어떻게 private에 못넣을까요?

Macuro의 이미지

private에 생성자,소멸자를 넣는이유가
class test : public Singleton
{};
일때
test A;
이렇게 객체를 못만들게 하려는 의도인데
private에 생성자,소멸자가 있다고 되는건지 급 혼란스러워 지네요;

익명 사용자의 이미지

protected라는 것도 있습니다. ^^

Macuro의 이미지

C++배우고나서 Protected를 쓸일이 없었어서 존재 의미를 잊어버렸었는데
이제야 알았네요 -_-;;

익명 사용자의 이미지

참고로, 위의 코드는 올바르게 싱글톤을 구현한것이 아닙니다.

if(m_pThis == NULL)
{
m_pThis = new T[1];
}
return m_pThis;

위의 코드가 문제인데요

if (m_pThis == NULL)과
m_pThis = new T[1]은 atomic operation이 아닙니다.

즉, 여러번의 operation으로 수행되는것이죠. (CPU level에서)

이것은, 여러개의 thread가 동시에 singleton에 접근할때 문제가 됩니다.

예를들어
두개의 쓰레드 A,B가 있다고 치고, 해당 getPointer()가 한번도 불려지지않았다고 가정합시다.
#1. A가 getPointer()를 호출한다
#2. B또한, getPointer()를 호출한다.
#3. A가 if (m_pThis == NULL)을 check 하고, 아무도 아직 new T[1]을 하지않았으므로, 그것은 true가 된다.
#4. B또한 if (m_pThis == NULL)을 check 하고, 아무도 아직 new T[1]을 하지않았으므로, 그것 또한 true가 된다.
#5. A가 m_pThis = new T[1]
#6. B가 m_pThis = new T[1]
#7. A가 생성한것은 잃어버리게 된다.

위의 시나리오는 아주 단순한것이고,
#5와 #6의 순서가 바뀔수도 있고
좀 더 나쁜 경우는
A가 생성한것을 잃어버리는게 아닌
A와 B가 각각 다른 객체를 얻게되버리는 최악의 경우도 발생할수 있습니다.

또한, CPU가 pipe-line에서 write-operations 를 reordering을 허용하느냐 안하느냐
(다행히, intel cpu들은 허용안합니다)
에 따라 memory barrier를 생각하셔야합니다.

write-operation re-ordering이 없는 환경에서의 가장 단순한 구현물은
double-checked locking인데요.

구글에서 double check locking singleton 으로 검색해보시면
자세한 설명들과 함께 코드까지 줄줄이 나옵니다.

http://www.ibm.com/developerworks/java/library/j-dcl/index.html
위의 article은 java를 기준으로 쓰여졌지만
어짜피 다 똑같은 얘기들입니다.

영어에 익숙하시다면, 정독하시길 추천드립니다.

Macuro의 이미지

쓰레드에 의해서 안전하지 않은것은 알겠지만 아래 CPU와 관련된 얘기는 넘겨짚어 이해했네요;
링크 달아주신 글은 한번 읽어보겠습니다. 문제는 영어에 그렇게 익숙하지 않다는 것이지만요

익명 사용자의 이미지

http://www.google.com/url?sa=t&source=web&cd=1&ved=0CBIQFjAA&url=http%3A%2F%2Fwww.aristeia.com%2FPapers%2FDDJ_Jul_Aug_2004_revised.pdf&ei=HrNfTeLlBIrIuAP_2PXJBA&usg=AFQjCNHmqLfgOdlZVKlZiSGCY1-KOooLzA

위의 문서는
Effective C++의 저자로도 유명한, Scott Meyer가 작성한
Double Locking Singleton Pattern에 대한 문서인데

제가 위에 언급한
모든 문제들이 예제와 함께 자세히 모두 설명되어있습니다.

CPU 구조와 pipeline, 그리고 memory barrier, complier barrier, volatile keyword in C 에 대해 어느정도 이해가 필요한 문서입니다.

가끔은 싱글톤의 구현을 단순하게 보시는 분들이 있던데,
생각보다 복잡한넘입니다;;;

익명 사용자의 이미지

Double Locking -> Double checked locking

댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.