2016-08-05 16 views
0

MSMブーストライブラリに慣れ親しんでいます。私はこれが本当に面白いと知ったquestionsいくつかの直交状態に加わることについて。MSMブーストライブラリで同じサブステートマシンの複数のインスタンスを実行するにはどうすればいいですか

また、ブーストのドキュメントでは、親ステートマシン内でサブステートマシンを再利用する方法を見つけました。シンプルなネストステートマシンをいくつかコーディングしました。

しかし、私はこの2つのものを混ぜ合わせる方法を頭で覆うことはできません。

私の目標は、同じサブ状態マシンのいくつかの独立したインスタンスにフォークし、それらが終了するまで待機してから、コントロールを親に戻すことです。

しかし、boost documentationは、サブステートマシンに直接フォークすることはできないと言います。

注:フォークにも有効です。現時点では、明示的なエントリのターゲットとしてサブマシンを使用することはできません。ほとんど同じ効果のためにエントリー擬似状態を使用してください。その後、

チケット飛行機を購入すると、サブステートマシンとしてモデルとなり得る

、あなたが価格を要求し、あなたがそれを購入することができますよりも、いくつかの評価を行い、(キャンセル及び秩序の無い完成も可能です)。しかし、同じ論理を複数の航空会社に適用することができます。 ここでは、市場をスキャンし、さまざまなプロバイダから一定量のチケットを予約するソフトウェアを作成するとします。 私たちは顧客から注文を受け取り、市場に照会し、4つの異なる航空会社から購入することに決めました(顧客は気にしません)。 これで、4つのサブステートマシンが並行して動作し、最後のオーダーが完了したときにのみ、コントロールが親ステートマシンに戻ります。 (私はこの例が素晴らしいとは思いませんが、あなたがそのアイデアを得たことを願っています)。

質問

それはフォークと同じ状態マシンのいくつかのインスタンスを使用(または擬似状態とほぼ同じ効果を実現)することは可能ですか?ステートマシンは、どのサブステートマシンがイベントを参照しているかをどのように知っていますか?

可能であれば、正しい方向に私を指摘できますか?私はこのブースト資料exampleについて知っていますが、実際に私の問題に対処していません。

私は自分のプロジェクトの初期段階ですから、必要に応じて別のステートマシンライブラリに移動することができます(ステートチャートも評価中です)。

答えて

1

直交状態は状態の異なる部分ではうまく動作しますが、同じイベントを処理すると思います。あなたの場合、複数のステートマシンインスタンスが必要です。あなたのケースを解決するために、私は2つの異なるステートマシンを定義する方が良いアプローチだと思います。彼らは親子関係は持っていませんが、お互いにイベントを送ります。

たとえば、マネージャとしての親状態マシンと、作業者としてのサブ状態マシンを考えてみましょう。

worker  

    +-----------+ 
+--|processing | 
| |   | 
| +-----------+ 
|  | 
|  | e_found(price)/a_notify(price) (send e_found(price) to the manager 
|  V 
| +-----------+ 
| |processed | 
| +-----------+ 
|e_cancel| 
|  V 
| +-----------+ 
+->|end  | 
    +-----------+ 


manager 

    +-------------------------------------------------------+ 
    |comparing            | 
    |entry/create 4 workers         | 
    |e_found(price)/increment count and compare price, etc| 
    +-------------------------------------------------------+ 
      | e_cancel/ propagate e_cancel to all workers 
      V 
    +-----------+ 
    |end  | 
    +-----------+ 

私はステートマシンがあなたのシナリオ例を示すと信じています。注:上記のオンラインコンパイラの出力は時々不安定ですが、私のローカル環境でコードをチェックしてうまくいきます。

私はticket price foundイベントをmain()に送ります。それは本当ではない。システムの他の部分から価格データを受け取っている可能性があります。しかし、それは必須のポイントではありません。

ステートマシン間でイベントを送信するために、私はmsm :: back :: state_machineのshared_ptrを使用します。ステートマシンのバックエンドを取得してprocess_eventを呼び出す必要がありますが、テンプレートパラメータFsmがフロントエンドです。そこで、ステートマシンのバックエンドのweak_ptrをメンバ変数としてステートマシンのフロントエンドに埋め込みました。私がprocess_event()を呼び出したいとき、get_sm()メンバ関数を使ってバックエンドのshared_ptrを取得しています。

このシナリオでは、キャンセルイベントがマネージャからワーカーに送信されます。見つかったイベントは、ワーカーからマネージャーに送信されます。

あなたが別のスレッドとして労働者を実行したい場合は、次のようにミューテックスを使用する必要があります。

http://melpon.org/wandbox/permlink/TrexYnffiwEpazNk

参照ライン100と192

がイベントをキャンセルマネージャによって処理さに伝播されますすべての労働者。キャンセル操作をテストするには、次のようにキャンセルイベントを挿入することができます。

int main() { 
    auto m = manager::create(); 
    m->workers_[0]->process_event(e_found {10}); 
    m->workers_[1]->process_event(e_found {20}); 
    m->process_event(e_cancel()); // Cancel !! 
    m->workers_[2]->process_event(e_found {30}); 
    m->workers_[3]->process_event(e_found {40}); 
    return 0; 
} 
+0

ありがとう、私は間違いなくあなたのアプローチを構築することができます。私は慎重にあなたの例を勉強するつもりです、ありがとう。 –

関連する問題