melt日記

.NETすらまともに扱えないへたれのページ

ホーム 連絡をする 同期する ( RSS 2.0 ) Login
投稿数  111  : 記事  3  : コメント  8233  : トラックバック  41

ニュース

わんくま同盟

わんくま同盟

C# と VB.NET の質問掲示板

iKnow!


Dictation



書庫

Template で Template Method というのは singleton に応用できるのではないかと思って作ってみました。

template<class T>
class Singleton
{
protected:
    Singleton() { }
 
public:
    static T* GetInstance()
    {
        static T t;
        return &t;
    }
};
class Hoge : public Singleton<Hoge>
{
public:
    ...
};

ものすごい簡単ですね。

まあ実際は引数に自身のクラス以外を渡すことも出来るので、singleton とは言えない気もしますが、許容範囲内ということにしておきます。


で、これをマルチスレッド対応にする場合、Windows ならクリティカルセクションを使って double checked locking を行う訳ですが、シングルスレッドの場合はクリティカルセクションに入る必要は無いので、何となくもったいないと感じます。

そこで登場するのが ATL のスレッドモデル。

これらはインクリメントとデクリメント、それからクリティカルセクションが、スレッドモデルに適した形で定義されています。

これらのスレッドモデルを使って書くと、

template<class T, class ThreadModel = CComSingleThreadModel>
class Singleton
{
private:
    static T* p;
    static typename ThreadModel::AutoCriticalSection cs;
 
protected:
    Singleton() { }
 
public:
    static T* GetInstance()
    {
        if (p == NULL)
        {
            cs.Lock();
            if (p == NULL)
            {
                try
                {
                    p = new T();
                }
                catch (...)
                {
                    cs.Unlock();
                    throw;
                }
            }
            cs.Unlock();
        }
        return p;
    }
};
 
template<class T, class ThreadModel>
    T* Singleton<T, ThreadModel>::p = NULL;
template<class T, class ThreadModel>
    typename ThreadModel::AutoCriticalSection Singleton<T, ThreadModel>::cs;
class Hoge : public Singleton<Hoge, CComMultiThreadModel>
{
public:
    ...
};

こうなります。

シングルスレッドの場合は cs.Lock() の中身はインラインで空き関数になっているので消えて、2回の NULL チェックは……どうなるんだろ?

その部分が最適化されるかどうかは分かりませんが、とりあえずクリティカルセクションに入るという処理は無くなります。


まあ実際のところ、singleton は最初の一回しか初期化されないのでクリティカルセクションに入っても全然構わないわけですが、複数のスレッドモデルで使う可能性があって、なおかつ速度を求めたい場合は使えるかもしれません。



余談:

生成に関する部分を new 以外で生成したい場合は、

template<class T, class ThreadModel = CComSingleThreadModel>
class Singleton
{
private:
    static T* p;
    static typename ThreadModel::AutoCriticalSection cs;
 
protected:
    Singleton() { }
 
    // デフォルト処理
    static T* Create() { return new T(); }
 
public:
    static T* GetInstance()
    {
        if (p == NULL)
        {
            cs.Lock();
            if (p == NULL)
            {
                try
                {
                    p = T::Create();
                }
                catch (...)
                {
                    cs.Unlock();
                    throw;
                }
            }
            cs.Unlock();
        }
        return p;
    }
};
 
template<class T, class ThreadModel>
    T* Singleton<T, ThreadModel>::p = NULL;
template<class T, class ThreadModel>
    typename ThreadModel::AutoCriticalSection Singleton<T, ThreadModel>::cs;
class Hoge : public Singleton<Hoge, CComMultiThreadModel>
{
public:
    static Hoge* CreateInstance() { return HogeFactory::Create(); }
 
    ...
};

こんな風にすればいいのかなぁと思ってみたり。

テンプレートってすげー。

投稿日時 : 2007年8月7日 13:33

コメント

# re: [C++]今更 singleton 2007/08/07 16:45 アキラ
Lokiっぽいなー

# re: [C++]今更 singleton 2007/08/07 23:43 melt
Loki って初めて知りましたw
確かに似てますねw

# XYHbPhWWYfocyfKTJtQ 2021/07/03 2:41 https://amzn.to/365xyVY
Loving the info on this site, you have done outstanding job on the articles.

# Illikebuisse zugyg 2021/07/04 19:35 pharmaceptica.com
malaria drug chloroquine https://pharmaceptica.com/

Post Feedback

タイトル
名前
Url:
コメント