シングルトンネタ続き

シングルトンをd:id:crimsonwoods:20061020のようなパターンとして実装するのに反対な理由。

(シングルトンなクラスをAとし、Aを使う側をBとする)

  • Aをシングルトンとして規定することで、AとBの間にシングルトンであるという依存性が形成されてしまう
  • Aをシングルトンでなくファクトリで生成したくなった場合などの修正コストがでかい
  • ダブルチェックロッキングのロジックなど、インスタンスの生成過程に関するロジックをAに加えなければならない

ということでtemplateを使ってSingletonにするラッパーを考えてみた。

template < class _Ty, class _Counter > class singleton_shared_ptr
{
private:
    mutable _Ty* _ptr;
    mutable _Counter _shared_counter;
public:
    singleton_shared_ptr( _Ty* ptr, _Counter* cnt )
        : _ptr( ptr ), _shared_counter( cnt )
    {
        if( 0 != _shared_counter )
        {
            ++*_shared_counter;
        }
    }

    singleton_shared_ptr( const singleton_shared_ptr& ptr )
        : _ptr( ptr._ptr ), _shared_counter( ptr._shared_counter )
    {
        if( 0 != _shared_counter )
        {
            ++*_shared_counter;
        }
    }

    ~singleton_shared_ptr()
    {
        if( 0 != _shared_counter )
        {
            --*_shared_counter;
        }
    }

    singleton_shared_ptr& operator = ( const singleton_shared_ptr& ptr )
    {
        if( this == &ptr )
        {
            return *this;
        }

        if( 0 != _shared_counter )
        {
            --*_shared_counter;
        }

        _ptr = ptr._ptr;
        _shared_counter = ptr._shared_counter;

        if( 0 != _shared_counter )
        {
            ++*_shared_counter;
        }

        return *this;
    }

    _Ty* operator -> () const
    {
        return _ptr;
    }

    _Ty& operator * () const
    {
        return *_ptr;
    }
};

tempalte < class _Ty, class _Counter = size_t, class _Ptr = singleton_shared_ptr< _Ty, _Counter > > class singleton
{
private:
    static _Ty*     _instance;
    static _Counter _shared_counter;
public:
    static _Ptr instance()
    {
        if( 0 == _instance )
        {
            _instance = new _Ty();
        }
        return _Ptr( _instance, &_shared_counter );
    }

    static void release()
    {
        if( 0 == _shared_counter )
        {
            delete _instance;
            _instance = 0;
        }
    }
};

tempalte < class _Ty, class _Counter, class _Ptr > _Ty* singleton::_instance = 0;
tempalte < class _Ty, class _Counter, class _Ptr > _Counter* singleton::_shared_counter = 0;

一応共有カウント付き。どうなんだろうなこれ。