2015/09/08

[smc]状態ごとに条件を変えて遷移できるか?

状態遷移のsmcは、使ってみればわかるだろう、と思っていたのだが、いきなり詰まった。

やりたいのは、A/D変換の結果によって遷移先を変えたいというもの。
ただ、その条件は状態によって違うのだ。
ありがちだと思うのだが、どこまでsmcでできるのだろうか?

状態に遷移するイベントを作って置いて、自分で状態ごとに値を判断してイベントを呼ぶ、というのは無しにしたい。
それだったら、普通に組んだ方がわかりやすいだろうし。

smcのページを見ていくと、タイトルとしてはこれが近いような気がする。
http://smc.sourceforge.net/SmcManSec2.htm#TransGuards

UMLのガードって、条件みたいなものではないか。
だから、条件による遷移、みたいな意味だったらよいと思ったのだ。
日本語だと「守る」って感じがしてしまうんだけどね。


ガードにはif文に書けるような条件を書いておけ、というように読める。
ただ、私がやりたいのは静的な条件では無く、状態によって変わる条件なのだ。
そういうのはどう表すのだろう?

コンテキストクラスのメソッドを呼びたいなら、ctxtを自分で付けろ、とある。
でも、Cだしなぁ。
というよりも、ctxtってなんだ?
thisみたいなものなら、引数にして渡してやれば同じことができるかもしれない。

 

どうやら、ctxtはコンテキストクラスを表す変数のようだ。
Cでのサンプルを見る限りでは、%classにつけた構造体名がそれに当たりそうだ。
では、試してみよう。

extern int AppClass_IsAcceptable(struct AppClass *this);

こんなヘッダをAppClass.hに書き、ソースにはこう。

int AppClass_IsAcceptable(struct AppClass *this)
{
    return this->isAcceptable;
}

特に意味はない関数なのだけど、サンプルソースで使えそうなのを入れてみただけだ。

そして、smファイルは

Zero    [AppClass_IsAcceptable(ctxt)]    Zeros    {}

遷移条件なので、遷移先の前に書くのだろう。
これは、Start状態のZeroイベントに書いたのだが、AppClass_sm.cにはこう反映されていた。

static void Map1_Start_Zero(struct AppClassContext *const fsm)
{
    struct AppClass *ctxt = getOwner(fsm);
    if (AppClass_IsAcceptable(ctxt)) {
        /* No actions. */
        setState(fsm, &Map1_Zeros);
    }
    else {
        Map1_DefaultState_Zero(fsm);
    }
}

AppClass_IsAcceptable()が真ならばZerosに遷移するし、そうでなければ・・・デフォルト状態?に遷移するようだ。

 

なので、Context Classを表す構造体のメンバに、判断する材料を全部突っ込んでおけばよいということになるか。


でも、C++みたいにvirtualで持つわけではないので、もうちょっとうまいことやらないと作業が楽にならないな。

状態を表すint型の0から始まる変数があって、それを添字にして関数を用意する、みたいなのが楽なんだけど、そういう感じでもなさそうだ。
そもそも、AppClassState構造体は状態ごとに別の実装を持てるようになっていそうだから、間借りさせてくれるとよいのだが。

0 件のコメント:

コメントを投稿

コメントありがとうございます。
スパムかもしれない、と私が思ったら、
申し訳ないですが勝手に削除することもあります。