2015-12-21 2 views
5

私は、examples/curl/curl_fuse.cpplibcaf_core/test/stateful_actor.cppの下で、stateful_actorの使い方を読んだことがあります。 stateful_actor<State>は、State structのフィールドを宣言することによって、俳優のいくつかの状態をバインドできるようです。それは非常に便利です。stateful_actorを理解する

同じ効果を得るために、状態をフィールドとしてclass-based actorに宣言できますか?または、stateful_actorには特別な処理(スレッドセーフなアクセスなど)がありますか?

次の例のアクタは同じ機能を提供しますか?

/* Class based actor */ 
struct ClassCounter : caf::event_based_actor 
{ 
    caf::behavior make_behavior() override { 
     return { 
      [=](inc_atom){ i += 1; } 
      , [=](ret_atom){ return i; } 
     }; 
    } 

    const char* name() const override { return "I am class-based"; } 
    int i = 0; 
}; 

/* Stateful actor */ 
struct CounterState 
{ 
    caf::local_actor* self; 
    int i = 0; 
    const char* name = "I am stateful"; 
}; 

caf::behavior StatefulCounter(caf::stateful_actor<CounterState>* self) 
{ 
    return { 
     [=](inc_atom){ self->state.i += 1; } 
     , [=](ret_atom){ return self->state.i; } 
    }; 
}; 

答えて

5

我々は、同様の効果を得るためにclass-based actorのフィールドとしての状態を宣言することはできますか?または、stateful_actorには特別な処理(スレッドセーフなアクセスなど)がありますか?

CAFのランタイムは、分離されるアクターを想定しています。つまり、アクター自体だけがその状態にアクセスすることができます。したがって、アクタの状態へのアクセスは決して同期されません。インターアクター間の通信はメッセージの受け渡しを使用するため、設計によって競合状態が回避されます。

ステートフルなアクターを使用すると、プログラマーはクラスを少なく書くことができます(したがって、定型コードは少なくなります)。ClassCounterStatefulCounter:変数の有効期間の間にも大きな違いがあります。 ClassCounterでは、メンバー変数iは、デストラクタClassCounterが呼び出されるまで存続します。アクターは参照カウントされるので、デストラクタは参照がない場合、つまりアクターにハンドルが存在しない場合はactorまたはactor_addrになります。 StatefulCounterでは、アクターが初期化された場合はCounterStateメンバーが作成され、アクターが終了した場合は破棄されます。

状態は、俳優が生きている間のみ存在します。これは、サイクルを中断させる場合に特に便利です。 2人の俳優ABがいる場合は、Aがメンバー変数を介してBへの参照を保持する場合はサイクルがあり、その逆もあります。ステートフルなアクタを使用する代わりに、このサイクルが壊れます。 Aは、終了時に自動的にBへの参照を解放し、その逆もあります。

+0

したがって、CounterStateのデストラクタは、アクタが終了すると呼び出されますか? –

+0

mm。私は国家と俳優の行動の懸念を分けることがメンテナンスの方が良いと思います。 –

+1

"したがって、CounterStateのデストラクタは、アクタが終了すると呼び出されますか?"はい。アクタはメールボックスを閉じ、終了するときにその状態を破棄します。また、必要に応じて終了メッセージや停止メッセージを表示します。それ以降の着信メッセージはすべて破棄され(同期メッセージのエラーメッセージが表示されます)、終了したアクタにリンクするとすぐに終了メッセージが表示されます。 – neverlord