テンプレートとマルチステートポリシーロック


テンプレートとマルチステートポリシーロック
分類:C++は脳死を促進する最良の方法である.
 
テンプレートとマルチステートポリシーロック
キーワード:戦略化モードモデル化戦略化多態戦略化戦略化ロックモードACE BOOST C++設計モード
 
ACEとBOOSTの実装には多くのポリシー化ロック(Strategized Locking)のモードがあり、このモードはあなたのクラスにロックとロックをかけない2つの状況を互換させるのに便利です.ACEの巨匠Douglas C.Schmidtには専門の論文「Strategized Locking」が紹介されており、国人Thzhangも「ACE戦略化のロックモード」を翻訳したことがある.
本論文の目的は,このモードの2つの実装方式のテンプレートパラメータと多態方式以外を紹介するとともに,両者の長所と短所を紹介することである.
 
テンプレートパラメータポリシーロック
モニタリングコンポーネントがマルチスレッド環境とシングルスレッド環境で同時に使用され、その使用率が非常に高い場合は、マルチスレッドでロックする必要がありますが、そのため、シングルスレッドでのコンポーネントのパフォーマンスに影響を及ぼす場合は、計算に合いませんが、各環境に世代コードを書くのは明らかにコードの再利用に不利です.では、2つのモードを互換化する方法はありますか?これがポリシー化されたロックのモードです.
戦略的にロックをかける方法は一般的にテンプレート(ACEとBOOSTは同じような方法で試したことがある)でこの機能を完成させ、これによるコストはコンパイラでほとんど性能に影響を与えない.次のコードがあります.
 
//ZEN_Null_Mutex             ,
class ZEN_Null_Mutex
{

public:

    //  ,        
    void lock()
    {
    }
    //  ,        
    void unlock()
    {
    }
}

//ZEN_Thread_Mutex             ,
class ZEN_Thread_Mutex
{
protected:
    //   
    pthread_mutex_t  lock_;
public:

    //  , ZEN_OS            ,     ,         mutex
    void lock()
    {
        ZEN_OS::pthread_mutex_lock(&lock_);
    }
    //  , 
    void unlock()
    {
        ZEN_OS::pthread_mutex_unlock(&lock_);
    }
}

//ZEN_Server_Status_T                     
//    _ZEN_LOCK                
template <class _ZEN_LOCK>
class ZEN_Server_Status_T
{

protected:
    //
    _ZEN_LOCK            stat_lock_;

public:

    //
    void increase_ byidx(size_t index, int64_t incre)
    {
        stat_lock_.lock();
        (stat_sandy_begin_ + index)->counter_ += incre;
        stat_lock_.unlock();
    }
    ……
}

 
上のコードtemplate class ZEN_Server_Status_Tはポリシーロック機能を備えた監視クラスであり、その中のテンプレートパラメータ_ZEN_LOCKはZEN_Null_MutexとZEN_Thread_Mutexは、異なる環境で異なるテンプレートパラメータを試用してZEN_を試用することができます.Server_Status_Tモニタコンポーネント.これでみんな大喜びして、
マルチスレッド環境では、次のように使用すると同期セキュリティが保護されます.
ZEN_Server_Status_T<ZEN_Thread_Mutex >::instance()->increase_byidx 

単一スレッド環境では、以下のように使用すると、最も速いパフォーマンスが得られます.
ZEN_Server_Status_T<ZEN_NULL_Mutex >::instance()->increase_byidx

 
このモードでは、読み書きロックを実現するなど、内部の動作を簡単に変えることができます.
このモードの最大の利点は、クラスのロック動作が必要かどうかの決定時間がコンパイル期間に置かれ、コードに異なる動作をもたらし、パフォーマンスのコストが最も低いことです.また、C++プログラマーにとって、モデル戦略化を試用するのはクールな表現で、彼はあなたのコードをもっと上流に見せます(このような要素の影響力を軽視しないでください).
 
テンプレートポリシー化の不足
実はDouglas C.Schmidtの論文「Strategized Locking」(残念ながらその年読んだときは能力が限られていて、体得できなかった)をよく読んでみると、このような一節に気づきます.
There are two ways to strategize locking mechanisms: polymorphism and parameterized types . In general, parameterized types should be used when the locking strategy is known at compile-time. Likewise,polymorphism should be used when the locking strategy is not known until run-time. As usual, the trade-off is between the efficient run-time performance of parameterized types versus the potential for run-time extensibility with polymorphism.
翻訳:ポリシー化ロックモード、マルチステートまたはテンプレートパラメータ化を実現する2つの方法があり、一般的にテンプレートパラメータ化はコンパイル時にロック動作を決定するために使用され、マルチステートは実行時にロックポリシーを決定する.通常、テンプレートパラメータ化メソッドを使用するか、マルチステートメソッドを使用するかを比較する要因は、実行時のパフォーマンスと実行時のマルチステート拡張性です.
最近、自分が書いたコードの中で上記の言葉に対していくつかの新しい認識がありました.コードの階層関係のため、私は監視のクラスを継承しなければなりません.そこで、同時にロックの効果を保証するため、私は依然としてテンプレートのロック戦略を使用しなければなりません.
 
//                  
template <class _ZEN_LOCK>
class Comm_Server_Status :public ZEN_Server_Status< _ZEN_LOCK >

 
これはまだ最も苦痛ではありません.監視の点が多いので、ベースライブラリ(実装ではなくライブラリに注意)のコードにも監視操作を追加しなければなりません.テンプレートのロックポリシーを維持し続けると、多くのコードを書き直さなければなりません.
//   ComponentA    ZEN_Server_Status,
//  Component_A        ,           ,                 
//                    
template <class _ZEN_LOCK>
class ComponentA
{

    int fun_a1
    {
        //       fun_a1        
        ZEN_Server_Status<_ZEN_LOCK >::instance()->increase_byidx
            ……
    }
}

//     B     ZEN_Server_Status,        
template <class _ZEN_LOCK>
class ComponentA
{
}

 
モニタリングを使用したい場所が多い場合は、大量のコードをテンプレートに変更する必要があります.また、ポリシーロックの方法を使用する必要があります.私もそれが全く不可能だとは思わないが、問題を拡大した疑いがある.特に、ComponentA自体がスレッド同期の要件を全く考慮する必要がない場合.
ACEのコードを観察すると、ACEのコードの大部分はテンプレート化されたロックポリシーを使用しているが、これは確かにACEの多くのコードに苦痛をもたらしている(ACE_LOCKを検索すればわかる)、ACEのすべてのタイマは実際にはテンプレート化されたポリシーロックモードを使用しているが、コードの便利さのために、ACEはオンラインスレッドロックがテンプレートパラメータのクラスとして継承されて使用されることが多い.例えばACE_Reactorのデフォルトはロックの実装であるため、本質的にはより良いパフォーマンスをもたらすことはありません.
//       
//ACE_Reactor
//   
//ACE_Select_Reactor_T<ACE_Reactor_Token_T<ACE_Token> >::handle_events(ACE_Time_Value & max_wait_time) 

 
 
マルチステートポリシー
では、マルチステートポリシー化を採用すれば、上記の問題をある程度回避することができますか?はい.マルチステート決定動作は,コンパイル時ではなく実行時であり,少量の性能損失があるが,動作時間の後方シフトを決定し,コードをある程度柔軟性を得た.
以下では,マルチステートを用いたポリシー化ロックを簡単に示す.
//       ,    ,ZEN_Lock_Base      ,
class ZEN_Lock_Base
{

public:

    //  ,        ,          ,
    visual void lock()
    {
    }
    //  ,        ,          ,
    visual void unlock()
    {
    }
}
typedef ZEN_Lock_Base ZEN_Null_Mutex;

//ZEN_Thread_Mutex             ,
class ZEN_Thread_Mutex :public ZEN_Lock_Base
{
protected:
    //   
    pthread_mutex_t  lock_;
public:

    //  , ZEN_OS            ,     ,         mutex
    visual void lock()
    {
        ZEN_OS::pthread_mutex_lock(&lock_);
    }
    //  , 
    visual void unlock()
    {
        ZEN_OS::pthread_mutex_unlock(&lock_);
    }
}

// ZEN_Server_Status_P                     
//    _ZEN_LOCK                
class ZEN_Server_Status_P
{

protected:
    //
    ZEN_Lock_Base         *stat_lock_;

public:
    //
    void init(bool multi_thread)
    {
        if (multi_thread )
        {
            stat_lock_ = ZEN_Null_Mutex();
        }
        else
        {
            stat_lock_= new ZEN_Thread_Mutex();
        }
    }

    //
    void increase_ byidx(size_t index, int64_t incre)
    {
        //      
        stat_lock_->lock();
        (stat_sandy_begin_ + index)->counter_ += incre;
        stat_lock_->unlock();
    }
    ……
}

 
 
ロックポリシーは、関数を初期化するときに決定することができ、テンプレートのパラメータの影響をさまざまな場所に拡大する必要はありません.例えばクラスライブラリでZENを大量に使用することもできますServer_Status_P、この時あなたは彼の具体的な行為を決める必要はありませんから.もちろん、ダイナミックは実行時に動作を決定するので、虚関数は多少性能オーバーヘッドが少ないのか、もちろん現在のCPU演算能力では、この問題をあまり考えなくてもいいです.
 
2つの戦略化の方法を比較する
テンプレートポリシー化は、テンプレートパラメータを使用してポリシー化を実現し、ポリシーの動作決定時間をコンパイル期間に配置し、パフォーマンスが最適です.しかし、適合コードの規模は大きくなく、あるいはそれ自体がテンプレートコードで使用されている(クールコードを追求している).また,ポリシー決定時間をコンパイル期間に置くため,継承し,大規模な使用時にもテンプレートポリシー動作を用いなければならない.戦略の影響を拡大する.
マルチステートポリシー化は、マルチステートメソッドを使用してポリシー動作を決定し、実行時に呼び出し者がパラメータによってどのマルチステート動作を使用するかを決定するとともに、決定動作が実行時に置かれるため、関連コードをそれほど変更する必要がなく使用できます.不十分なのは、パフォーマンスがテンプレートのポリシー化よりも少し弱く、実行中に呼び出し者がポリシーの動作を制御する必要があることです.
比較すると、マルチステートポリシー化はより良い応用シーンがあると思います.個人的には、過度なテンプレート設計はかえってコードの可用性を低下させ、使用者に影響を与えることがあるような気がします.
 
[本文の作者は雁渡寒潭で、自由の精神に基づいて、あなたは利益のない情況で完全にこのドキュメントを転載することができて、転載する時BLOGリンクを添付してください:http://www.cnblogs.com/fullsail/またはhttp://blog.csdn.net/fullsailあ、そうでなければ1字1元で、図100ごとに値切らない.Baidu文庫に2倍値上げ