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;
}
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();
}
'C++11,14 (modern C++)' 카테고리의 다른 글
String Compare (without space and special char) (0) | 2018.11.12 |
---|---|
rvalue reference 가 항상 유익하지 않다? (2) | 2017.04.07 |
C++ 11과 C++ 99 를 동시에 지원하기 위해서 feature를 구분할 때 유용한 팁 (0) | 2016.09.07 |
gcc와 c++ feature (0) | 2016.07.18 |
stl : map 과 array 성능비교. (2) | 2016.06.09 |