読者です 読者をやめる 読者になる 読者になる

シングルトンのベターな実装方法

mozc式シングルトンをお勧めらしい。
mozcはGoogle IMEです。

singletonのテンプレートクラスを使う。


singleton.h

class SingletonFinalizer
{
public:
    typedef void(*FinalizerFunc)();

    static void addFinalizer(FinalizerFunc func);
    static void finalize();
};

template <typename T>
class singleton final
{
public:
    static T& get_instance()
    {
        std::call_once(initFlag, create);
        assert(instance);
        return *instance;
    }

private:
    static void create() {
        instance = new T;
        SingletonFinalizer::addFinalizer(&singleton<T>::destroy);
    }

    static void destroy() {
        delete instance;
        instance = nullptr;
    }

    static std::once_flag initFlag;
    static T* instance;
};

template <typename T> std::once_flag singleton<T>::initFlag;
template <typename T> T* singleton<T>::instance = nullptr;

singleton.cpp

const  int kMaxFinalizersSize = 256;
static int gNumFinalizersSize = 0;
static SingletonFinalizer::FinalizerFunc gFinalizers[kMaxFinalizersSize];

void SingletonFinalizer::addFinalizer(FinalizerFunc func) {
    assert(gNumFinalizersSize < kMaxFinalizersSize);
    gFinalizers[gNumFinalizersSize++] = func;
}

void SingletonFinalizer::finalize() {
    for (int i = gNumFinalizersSize - 1; i >= 0; --i) {
        (*gFinalizers[i])();
    }
    gNumFinalizersSize = 0;
}


使い方。

void main() {
    Foo& gFoo = singleton<Foo>::get_instance();
    Bar& gBar = singleton<Bar>::get_instance();
    SingletonFinalizer::finalize();
}

SingletonFinalizer::finalize();を明示的に呼ぶことで解放処理をコントロールできます。


ネタ元