반응형

유용하면서 간단한 디자인패턴 : 싱글톤 패턴

 

Singleton class  Basic type

 

 

public class Singleton {
	private volatile static Singleton uniqueInstance = null;
	
	private Singleton() {}
	public static Singleton getInstance (){
		if ( uniqueInstance == null){
			synchronized( Singleton.class){
				if (uniqueInstance == null)
					uniqueInstance = new Singleton();
			}
		}
		return uniqueInstance;
	}
}

 

 

 

'개발 Note > Codes' 카테고리의 다른 글

[Andriod] Timer and TimerTask  (0) 2020.10.22
sorting algorithms  (0) 2014.02.26
UML2 Sementics  (0) 2012.01.11
반응형



Singleton pattern은 객체의 인스턴스가 process내에서 1개만 생성되도록 하는 것입니다.


이렇게 하기 위해서는 global 객체를 하나만 유지하고, 일반적으로 getInstance() 와 같은 class의 스테틱 메소드(static method)를 통해서 생성된 instance를 얻어가는 구조입니다.


주로 XXXX Manager 와 같은 management instance 류 들이 singleton으로 작성됩니다.



가장 simple한 구현체는 아래와 같은 형식입니다.


class Singleton

{

  public:

    static Singleton* getInstance();

  private:

    Singleton()=default;

};


Singleton* 

Singleton::getInstance();

{

    static Singleton inst;

    return &inst;

}

또는 

Singleton* 

Singleton::getInstance();

{

    static Singleton* inst = new Singleton();

    return inst;

}

또는 

static Singleton* __inst = nullptr;

Singleton* 

Singleton::getInstance();

{

    if(__inst == nullptr)

    {

       __inst = new Singleton();

    }

    return __inst;

}


하지만, 이렇게 작성된 코드는 객체 생성 시점에 쓰레드 세이프(thread safe)하지 않기 때문에 , single thread환경에서는 이슈가 없겠지만,

multi-thread환경에서는 이슈가 생길 가능성이 다분합니다.


이를 위해서 각 platform 환경에 맞춰서 thread safe 형식을 추가하여 작업을 해야 하는 상황이 발생하죠.

pthread 를 지원하는 환경이면, pthread_once 와 같은 함수들 말이죠.



C++ 11에서 부터는 언어 차원에서 pthread_once 와 같은 기능을 할 수 있는 기능을 지원하게 되었습니다.

std::call_once() 입니다. (http://www.cplusplus.com/reference/mutex/call_once/?kw=call_once)


이 call_once를 이용하면 platform과 연관성을 줄이면서 Singleton 디자인 패턴(design pattern)을 완성 할 수 있습니다.


[std::call_once를 이용한 Singleton pattern 구현]

#include <new>

#include <memory>

#include <mutex>

#include <stdio.h>


class Singleton

{

public:

    static Singleton& getInstance();


    void log(){

        printf("instance: %p", __instance.get());

    }

    ~Singleton(){

        printf("delete instance : %p", this);

    }

private:

    Singleton() = default;

    

    Singleton(const Singleton &) = delete;

    Singleton &operator=(const Singleton &) = delete;


    static std::unique_ptr<Singleton> __instance;

    static std::once_flag __once;

};



std::unique_ptr<Singleton> Singleton::__instance;

std::once_flag Singleton::__once;


Singleton& 

Singleton::getInstance()

{

    std::call_once(__once, []() {

      __instance.reset(new Singleton);


      printf("create instance : %p\n", __instance.get());


    });


    return *__instance.get();

}


void 

test_std_once()

{

    Singleton& ins= Singleton::getInstance();    

    ins.log();

}








+ Recent posts