boostsapporomsmpre 111030054504-phpapp02

95
Boost.Msmの使い方 Copyright 2011 Takatoshi Kondo All rights reserved 1/95

Upload: takatoshi-kondo

Post on 02-Aug-2015

49 views

Category:

Technology


0 download

TRANSCRIPT

Boost.Msmの使い方

Copyright 2011 Takatoshi Kondo All rights reserved

1/95

自己紹介

近藤 貴俊

BLOG http://d.hatena.ne.jp/redboltz/

twitter @redboltz

C++標準化委員会メンバ

技術士(情報工学部門)

GCJJ Tシャツ圏内

Copyright 2011 Takatoshi Kondo All rights reserved

2/95

目次

• StateMachineとは

• Boost Meta State Machine Library

• ATMを題材としたケーススタディ

• StateMachineDiagram(UML2.x)への対応状況

Copyright 2011 Takatoshi Kondo All rights reserved

4/95

StateMachineとは

State Machine

Event [Output]

Event Driven Outputは、あったりなかったり

EventA EventA

Outupt1

Outupt2

同じEventでも Outputが変わったり

中身は、 と

Copyright 2011 Takatoshi Kondo All rights reserved

5/95

StateMachineの構成要素

State1

event [ guard ] / action

entry / action do / action exit / action event [ guard ] / action

Copyright 2011 Takatoshi Kondo All rights reserved

6/95

StateMachineの構成要素

State1

event [ guard ] / action

状態 遷移

entry / action do / action exit / action event [ guard ] / action

Copyright 2011 Takatoshi Kondo All rights reserved

7/95

StateMachineの構成要素

State1

event [ guard ] / action

Output

Event

entry / action do / action exit / action event [ guard ] / action

Copyright 2011 Takatoshi Kondo All rights reserved

8/95

遷移 Transition State1 State2 event [ guard ] / action

遷移元状態(State1)において、eventが発生した際、 guardが成立していれば、遷移先状態(State2)に遷移する。 遷移の際、actionを実行する。

event guard action は、いずれもoptional

• guard記述がなければ、eventが発生した際、無条件に 遷移先状態に遷移する。

• action記述がなければ、遷移の際、特に何も実行しない。

• event記述が無い場合の意味論は後述

Copyright 2011 Takatoshi Kondo All rights reserved

9/95

内部遷移 Internal Transition State1

event [ guard ] / action

遷移先状態を指定しない遷移。状態遷移は発生しない。 状態の内部に記述する(UMLの表記法) あるEvent発生時、guardに応じてactionを実行することを 目的として記述される。

遷移しない遷移なんだから、actionを書かないと意味がない

Copyright 2011 Takatoshi Kondo All rights reserved

10/95

遷移 Transition State1 State2 event [ guard ] / action

event記述がなければ、 トリガとなったevent処理のなかで本遷移が評価される。

State1 State2

Guardが成立するまで待って、 成立したら遷移ではないので注意

Event1

Event1の発生でState2まで遷移する

State1 State2 Event1 [G1]

E2/G1=true

G1がfalseならState1まで遷移して待ち状態になる その後、eventによらず、G1がtrueになっても遷移は発生しない

E2が発生したらState2に遷移する

Copyright 2011 Takatoshi Kondo All rights reserved

11/95

状態 State

状態名

entry/action1 do/action2 exit/action3 event[guard]/action4

(普通の)状態 Composite State

この状態に遷移する際に実行されるentry action

この状態から遷移する際に実行されるexit action

その状態の間常に実行されるdo action Event Drivenなソフトウェアではあまり使わない サブマシン状態を持つという記号

include / 他の状態マシン

内部に持つサブマシン名

内部遷移(前述)

Boost.Msmでもサポートしない

Copyright 2011 Takatoshi Kondo All rights reserved

12/95

その他の構成要素 初期疑似状態 Initial Pseudo State

終了状態 Final State

ジャンクション疑似状態 Junction Pseudo State 見た目が初期疑似状態と一緒って。。。

選択疑似状態 Choice Pseudo State

State entry point疑似状態 Entry Point Pseudo State

exit point疑似状態 Exit Point Pseudo State

State

State

State

fork join H

H *

shallow history

deep history

本プレゼンでは ちょっと小さめに書きます

Copyright 2011 Takatoshi Kondo All rights reserved

13/95

参考文献

http://www.wisdom.weizmann.ac.il/~dharel/reactive_systems.html

絶版だが、以下のご本人サイトから PDFダウンロード可能

元々のStatechart

http://www.uml.org/

Current version: 2.4 (Beta)

UML2.xのStateMachineDiagramとして拡張

Copyright 2011 Takatoshi Kondo All rights reserved

14/95

Boost.Msmとは?

State

状態遷移を司るライブラリです

外部からのeventをキューイングしたり

スレッドでイベントループを実現したり

しません

内部のeventはキューイング されるけど

Copyright 2011 Takatoshi Kondo All rights reserved

15/95

Boost.Msmとは?

• そういう外回り?のことは、 Boost.AsioやBoost.Threadなんかで やってください

• 逆にいえば、Threadなしの周期モデル (組み込み開発などでよくある) でも使うことができます

Copyright 2011 Takatoshi Kondo All rights reserved

16/95

Boost.Msm

#include <boost/msm/back/state_machine.hpp> #include <boost/msm/front/state_machine_def.hpp> #include <boost/msm/front/functor_row.hpp>

namespace msm = boost::msm; namespace msmf = boost::msm::front; namespace mpl = boost::mpl;

struct Event1 {}; struct Event2 { int param1; int param2; };

eventはクラスで表現

パラメタはメンバとして

Copyright 2011 Takatoshi Kondo All rights reserved

17/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm StateMachineの定義

状態の定義

guardの定義

actionの定義 初期状態の定義(必須)

遷移の定義

eventに対応する遷移がないときの処理

Copyright 2011 Takatoshi Kondo All rights reserved

18/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm StateMachineの定義

Copyright 2011 Takatoshi Kondo All rights reserved

19/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

状態の定義

State1

entry/on_entry exit/on_exit

名前は予約されている

名前は予約されている

Copyright 2011 Takatoshi Kondo All rights reserved

20/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

State1

entry/on_entry exit/on_exit

遷移トリガとなったeventの参照

状態マシンSm_の参照

Copyright 2011 Takatoshi Kondo All rights reserved

21/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

boolをreturn

guardの定義

Copyright 2011 Takatoshi Kondo All rights reserved

22/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

guardの定義

boolをreturn

event, 状態マシン, 遷移元state, 遷移先state にアクセス可能

Copyright 2011 Takatoshi Kondo All rights reserved

23/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

actionの定義

event, 状態マシン, 遷移元state, 遷移先state にアクセス可能

Copyright 2011 Takatoshi Kondo All rights reserved

24/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

初期状態の定義(必須)

State1

Copyright 2011 Takatoshi Kondo All rights reserved

25/95

initial_stateの役割 State1

State1A

State1B

folk

join

State1C

E1

E1 E2

リージョン0

リージョン1 リージョンとは、状態を持つ単位 この例では、State1AかつState1Bといった状態が存在する

Copyright 2011 Takatoshi Kondo All rights reserved

26/95

initial_stateの役割 State1

State1A

State1B

folk

join

State1C

E1

E1 E2

リージョン0

リージョン1 リージョンとは、状態を持つ単位 この例では、State1AかつState1Bといった状態が存在する

typedef mpl::vector<State1A, State1B> initial_state;

Boost.MSMでは、initial_stateのtypedefをリージョンの表現に(も)利用する

1個の場合mpl::vectorじゃなくてもいい

この並びがリージョン番号

Copyright 2011 Takatoshi Kondo All rights reserved

27/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

遷移の定義

State1 State2 Event1 [ Guard1 ] / Action1

Copyright 2011 Takatoshi Kondo All rights reserved

28/95

state番号と評価順序

struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 >, msmf::Row < State2, Event2, State1, Action1, Guard1 >, msmf::Row < State2, Event2, State3, Action1, Guard1 >, msmf::Row < State5, Event3, State6, Action1, Guard1 >, msmf::Row < State4, Event4, State2, Action1, Guard1 > > {};

0

1

2

3

4

5

State番号の振られ方 遷移の評価順序

Copyright 2011 Takatoshi Kondo All rights reserved

29/95

state番号と評価順序

struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 >, msmf::Row < State2, Event2, State1, Action1, Guard1 >, msmf::Row < State2, Event2, State3, Action1, Guard1 >, msmf::Row < State5, Event3, State6, Action1, Guard1 >, msmf::Row < State4, Event4, State2, Action1, Guard1 > > {};

State番号の振られ方 遷移の評価順序

State2においてEvent2が発生した際 2つの遷移条件が成立するが、下の方が

評価順序の結果、優先される

Copyright 2011 Takatoshi Kondo All rights reserved

30/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm

eventに対応する遷移がないときの処理

定義しないとassertion fail

State番号 Copyright 2011 Takatoshi Kondo All rights reserved

31/95

struct Sm_:msm::front::state_machine_def<Sm_> { struct State1:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) {} template <class Event,class Fsm> void on_exit(Event const&, Fsm&) {} }; struct State2:msm::front::state<> { }; struct Guard1 { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; struct Action1 { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState&, TargetState&) const {} }; typedef State1 initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < State1, Event1, State2, Action1, Guard1 > > {}; template <class Fsm,class Event> void no_transition(Event const& e, Fsm& ,int state) {} };

Boost.Msm StateMachineの定義

状態の定義

guardの定義

actionの定義 初期状態の定義(必須)

遷移の定義

eventに対応する遷移がないときの処理

Copyright 2011 Takatoshi Kondo All rights reserved

32/95

ATMを題材としたケーススタディ

Copyright 2011 Takatoshi Kondo All rights reserved

33/95

ATMを題材としたケーススタディ

• StateMachineの階層化

• StateMachineのインターフェースと 実装の分離

• 複数の entry point疑似状態の使い分け

• サブStateMachineから親StateMachineへのEventの伝搬

• guardによるif/else分岐

Copyright 2011 Takatoshi Kondo All rights reserved

34/95

4つのStateMachine 1.全体 2.取引

3.引き出し 4.(生体)認証

Copyright 2011 Takatoshi Kondo All rights reserved

35/95

1.ATM(全体)

接客中 待機中

entry/画面消去 人物感知

人物離脱感知

include / 取引

全体

Copyright 2011 Takatoshi Kondo All rights reserved

36/95

1.ATM(全体)

接客中 待機中

entry/画面消去 人物感知

人物離脱感知

include / 取引

全体

内部がサブStateMachineであることを示す記号

サブStateMachine

ちなみに、UML的にはサブマシン状態という

Copyright 2011 Takatoshi Kondo All rights reserved

37/95

1.ATM(全体)

接客中 待機中

entry/画面消去 人物感知

人物離脱感知

include / 取引

全体

内部状態に手を加えずにキャンセル系処理を実現

この中がどんな状態でも脱出できるということ Copyright 2011 Takatoshi Kondo All rights reserved

38/95

2.ATM(取引)

引き出し選択 include / 引き出し

取引選択中

entry/取引選択画面提示

引き出し中

entry exit

取引

カード挿入 entry_by_card

その他選択 省略

Copyright 2011 Takatoshi Kondo All rights reserved

39/95

2.ATM(取引)

引き出し選択 include / 引き出し

取引選択中

entry/取引選択画面提示

引き出し中

entry exit

取引

カード挿入 entry_by_card

その他選択 省略

取引単位などで、階層化、モジュール化

Copyright 2011 Takatoshi Kondo All rights reserved

40/95

2.ATM(取引)

引き出し選択 include / 引き出し

取引選択中

entry/取引選択画面提示

引き出し中

entry exit

取引

カード挿入 entry_by_card

その他選択 省略

複数のentry point

Copyright 2011 Takatoshi Kondo All rights reserved

41/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

42/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

カード挿入済みの場合

Copyright 2011 Takatoshi Kondo All rights reserved

43/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

引き出し以外の取引でも 利用可能(振り込みとか)

Copyright 2011 Takatoshi Kondo All rights reserved

44/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

生体認証で実現

認証というインターフェース

Copyright 2011 Takatoshi Kondo All rights reserved

45/95

3.ATM(引き出し)

include / パスワード認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

実現方法の差し替え

Copyright 2011 Takatoshi Kondo All rights reserved

46/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

ジャンクション疑似状態による if / else 分岐

Copyright 2011 Takatoshi Kondo All rights reserved

47/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報 内部遷移

Copyright 2011 Takatoshi Kondo All rights reserved

48/95

4.ATM(認証) entry

exit_success

exit_fail

指検出

認証失敗

認証成功(アカウント情報)

生体認証

認証中

entry/認証中画面提示, 認証開始

指待ち

entry/指要求画面提示

タイムアウト

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

49/95

4.ATM(認証) entry

exit_success

exit_fail

指検出

認証失敗

認証成功(アカウント情報)

生体認証

認証中

entry/認証中画面提示, 認証開始

指待ち

entry/指要求画面提示

タイムアウト

アカウント情報

合流にも使える ジャンクション疑似状態

Copyright 2011 Takatoshi Kondo All rights reserved

50/95

4.ATM(認証) entry

exit_success

exit_fail

指検出

認証失敗

認証成功(アカウント情報)

生体認証

認証中

entry/認証中画面提示, 認証開始

指待ち

entry/指要求画面提示

タイムアウト

アカウント情報

アカウント情報を ステートマシン外部へ渡す

Copyright 2011 Takatoshi Kondo All rights reserved

51/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

イベントは存在しないが、 Boost.Msmでは伝搬用イベントを定義可能

Copyright 2011 Takatoshi Kondo All rights reserved

52/95

シナリオ

Copyright 2011 Takatoshi Kondo All rights reserved

53/95

1.ATM(全体)

接客中 待機中

entry/画面消去 人物感知

人物離脱感知

include / 取引

全体

Copyright 2011 Takatoshi Kondo All rights reserved

54/95

2.ATM(取引)

引き出し選択 include / 引き出し

取引選択中

entry/取引選択画面提示

引き出し中

entry exit

取引

カード挿入 entry_by_card

その他選択 省略

Copyright 2011 Takatoshi Kondo All rights reserved

55/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

56/95

4.ATM(認証) entry

exit_success

exit_fail

指検出

認証失敗

認証成功(アカウント情報)

生体認証

認証中

entry/認証中画面提示, 認証開始

指待ち

entry/指要求画面提示

タイムアウト

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

57/95

3.ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

58/95

2.ATM(取引)

引き出し選択 include / 引き出し

取引選択中

entry/取引選択画面提示

引き出し中

entry exit

取引

カード挿入 entry_by_card

その他選択 省略

Copyright 2011 Takatoshi Kondo All rights reserved

59/95

実装

Copyright 2011 Takatoshi Kondo All rights reserved

60/95

ATM(全体)

接客中 待機中

entry/画面消去 人物感知

人物離脱感知

include / 取引

全体

Copyright 2011 Takatoshi Kondo All rights reserved

61/95

ATM(全体) #include "atm_trade.hpp" namespace Atm { struct HumanDetect {}; struct HumanAway {}; struct All_:msm::front::state_machine_def<All_> { struct Waiting:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Clear Screen" << std::endl; } }; struct InService:Trade {}; typedef Waiting initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Waiting, HumanDetect, InService, msmf::none, msmf::none >, msmf::Row < InService, HumanAway, Waiting, msmf::none, msmf::none > > {}; }; typedef msm::back::state_machine<All_> All; }

Copyright 2011 Takatoshi Kondo All rights reserved

62/95

ATM(全体) #include "atm_trade.hpp" namespace Atm { struct HumanDetect {}; struct HumanAway {}; struct All_:msm::front::state_machine_def<All_> { struct Waiting:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Clear Screen" << std::endl; } }; struct InService:Trade {}; typedef Waiting initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Waiting, HumanDetect, InService, msmf::none, msmf::none >, msmf::Row < InService, HumanAway, Waiting, msmf::none, msmf::none > > {}; }; typedef msm::back::state_machine<All_> All; }

サブStateMachineは継承

Copyright 2011 Takatoshi Kondo All rights reserved

63/95

ATM(全体) #include "atm_trade.hpp" namespace Atm { struct HumanDetect {}; struct HumanAway {}; struct All_:msm::front::state_machine_def<All_> { struct Waiting:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Clear Screen" << std::endl; } }; struct InService:Trade {}; typedef Waiting initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Waiting, HumanDetect, InService, msmf::none, msmf::none >, msmf::Row < InService, HumanAway, Waiting, msmf::none, msmf::none > > {}; }; typedef msm::back::state_machine<All_> All; }

front_endとの対応付け

back_endとの対応付け

Copyright 2011 Takatoshi Kondo All rights reserved

64/95

ATM(全体) namespace Atm { struct HumanDetect {}; struct HumanAway {}; template <class AuthMethod> struct All_:msm::front::state_machine_def<All_<AuthMethod> > { // States struct Waiting:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Clear Screen" << std::endl; } }; struct InService:Trade<AuthMethod> {}; typedef Waiting initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Waiting, HumanDetect, InService, msmf::none, msmf::none >, msmf::Row < InService, HumanAway, Waiting, msmf::none, msmf::none > > {}; }; template <class AuthMethod> struct All:msm::back::state_machine<All_<AuthMethod> > {}; }

C++11なら template <class AuthMethod> using All = msm::back::state_machine<All_<AuthMethod>>;

認証の実装を差し替えるためにテンプレート化する

struct All_:msm::front::state_machine_def<All_>

typedef msm::back::state_machine<All_> All;

Copyright 2011 Takatoshi Kondo All rights reserved

65/95

ATM(取引)

引き出し選択 include / 引き出し

取引選択中

entry/取引選択画面提示

引き出し中

entry exit

取引

カード挿入 entry_by_card

その他選択 省略

Copyright 2011 Takatoshi Kondo All rights reserved

66/95

#include "atm_withdraw.hpp" #include "atm_card_detect.hpp" namespace Atm { struct ChooseWithdraw {}; template <class AuthMethod> struct Trade_:msm::front::state_machine_def<Trade_<AuthMethod> > { struct Choosing:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "1.Withdraw, 2.N/A, 3.N/A ..." << std::endl; } }; struct Withdrawing:Withdraw<AuthMethod> {}; typedef Choosing initial_state;

ATM(取引)

続く

Copyright 2011 Takatoshi Kondo All rights reserved

67/95

#include "atm_withdraw.hpp" #include "atm_card_detect.hpp" namespace Atm { struct ChooseWithdraw {}; template <class AuthMethod> struct Trade_:msm::front::state_machine_def<Trade_<AuthMethod> > { struct Choosing:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "1.Withdraw, 2.N/A, 3.N/A ..." << std::endl; } }; struct Withdrawing:Withdraw<AuthMethod> {}; typedef Choosing initial_state;

ATM(取引)

続く

認証を実現するテンプレート引数を伝搬

Copyright 2011 Takatoshi Kondo All rights reserved

68/95

ATM(取引)

typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::Entry> WithdrawEntry; typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::EntryByCard> WithdrawEntryByCard; typedef typename Withdrawing::template exit_pt <typename Withdraw_<AuthMethod>::Exit> WithdrawExit; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Choosing, ChooseWithdraw, WithdrawEntry, msmf::none, msmf::none >, msmf::Row < Choosing, CardDetect, WithdrawEntryByCard, msmf::none, msmf::none >, msmf::Row < WithdrawExit, msmf::none, Choosing, msmf::none, msmf::none > > {}; }; template <class AuthMethod> struct Trade:msm::back::state_machine<Trade_<AuthMethod> > {}; }

Copyright 2011 Takatoshi Kondo All rights reserved

69/95

ATM(取引)

typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::Entry> WithdrawEntry; typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::EntryByCard> WithdrawEntryByCard; typedef typename Withdrawing::template exit_pt <typename Withdraw_<AuthMethod>::Exit> WithdrawExit; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Choosing, ChooseWithdraw, WithdrawEntry, msmf::none, msmf::none >, msmf::Row < Choosing, CardDetect, WithdrawEntryByCard, msmf::none, msmf::none >, msmf::Row < WithdrawExit, msmf::none, Choosing, msmf::none, msmf::none > > {}; }; template <class AuthMethod> struct Trade:msm::back::state_machine<Trade_<AuthMethod> > {}; }

認証を実現するテンプレート引数を伝搬

Copyright 2011 Takatoshi Kondo All rights reserved

70/95

ATM(取引)

typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::Entry> WithdrawEntry; typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::EntryByCard> WithdrawEntryByCard; typedef typename Withdrawing::template exit_pt <typename Withdraw_<AuthMethod>::Exit> WithdrawExit; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Choosing, ChooseWithdraw, WithdrawEntry, msmf::none, msmf::none >, msmf::Row < Choosing, CardDetect, WithdrawEntryByCard, msmf::none, msmf::none >, msmf::Row < WithdrawExit, msmf::none, Choosing, msmf::none, msmf::none > > {}; }; template <class AuthMethod> struct Trade:msm::back::state_machine<Trade_<AuthMethod> > {}; }

Copyright 2011 Takatoshi Kondo All rights reserved

71/95

ATM(取引)

typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::Entry> WithdrawEntry; typedef typename Withdrawing::template entry_pt<typename Withdraw_<AuthMethod>::EntryByCard> WithdrawEntryByCard; typedef typename Withdrawing::template exit_pt <typename Withdraw_<AuthMethod>::Exit> WithdrawExit; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Choosing, ChooseWithdraw, WithdrawEntry, msmf::none, msmf::none >, msmf::Row < Choosing, CardDetect, WithdrawEntryByCard, msmf::none, msmf::none >, msmf::Row < WithdrawExit, msmf::none, Choosing, msmf::none, msmf::none > > {}; }; template <class AuthMethod> struct Trade:msm::back::state_machine<Trade_<AuthMethod> > {}; }

Copyright 2011 Takatoshi Kondo All rights reserved

72/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

73/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

struct Entry :msm::front::entry_pseudo_state<> {}; struct EntryByCard:msm::front::entry_pseudo_state<> {};

カード未挿入の場合

カード挿入済みの場合

entry point 疑似状態の実装

state

Copyright 2011 Takatoshi Kondo All rights reserved

74/95

参考 entry point疑似状態と並行状態

State1 entryA

struct EntryA:msm::front::entry_pseudo_state<> {}; struct EntryB:msm::front::entry_pseudo_state<> {}; struct EntryC:msm::front::entry_pseudo_state<> {}; struct EntryD:msm::front::entry_pseudo_state<1> {}; typedef mpl::vector<State1, entryC> initial_state;

entry point 疑似状態の実装

entryC

State0

State3

State4 entryD

リージョン番号

リージョン0 リージョン1

省略したらinitial_stateからの 到達で判断

entryB

State2 E1

initial_stateをentryに

することも可能

Copyright 2011 Takatoshi Kondo All rights reserved

75/95

参考 entry point疑似状態と並行状態

State1 entryA

struct EntryA:msm::front::entry_pseudo_state<> {}; struct EntryB:msm::front::entry_pseudo_state<> {}; struct EntryC:msm::front::entry_pseudo_state<> {}; struct EntryD:msm::front::entry_pseudo_state<1> {}; typedef mpl::vector<State1, entryC> initial_state;

entry point 疑似状態の実装

entryC

State0

State3

State4 entryD

リージョン番号

リージョン0

省略したらinitial_stateからの 到達で判断

entryB

State2 E1

Copyright 2011 Takatoshi Kondo All rights reserved

76/95

参考 entry point疑似状態と並行状態

State1 entryA

struct EntryA:msm::front::entry_pseudo_state<> {}; struct EntryB:msm::front::entry_pseudo_state<> {}; struct EntryC:msm::front::entry_pseudo_state<> {}; struct EntryD:msm::front::entry_pseudo_state<1> {}; typedef mpl::vector<State1, entryC> initial_state;

entry point 疑似状態の実装

entryC

State0

State3

State4 entryD

リージョン番号

省略したらinitial_stateからの 到達で判断

entryB

State2 E1

リージョン1

Copyright 2011 Takatoshi Kondo All rights reserved

77/95

参考 entry point疑似状態と並行状態

State1 entryA

struct EntryA:msm::front::entry_pseudo_state<> {}; struct EntryB:msm::front::entry_pseudo_state<> {}; struct EntryC:msm::front::entry_pseudo_state<> {}; struct EntryD:msm::front::entry_pseudo_state<1> {}; typedef mpl::vector<State1, entryC> initial_state;

entry point 疑似状態の実装

entryC

State0

State3

State4 entryD

リージョン番号

リージョン0 リージョン1

省略したらinitial_stateからの 到達で判断

entryB

State2 E1

initial_stateから 到達不可の場合、 リージョン番号の 指定が必須

Copyright 2011 Takatoshi Kondo All rights reserved

78/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

template <class AuthMethod> struct Withdraw_:msm::front::state_machine_def<Withdraw_<AuthMethod> > { struct WithdrawAuth:AuthMethod {};

パラメータ化された実装の状態への反映

state

int main() { Atm::All<Atm::BioAuth> t;

client

ここで認証方式を差し替えられる

StateMachine

最上階層から伝搬させてきた template parameter

Copyright 2011 Takatoshi Kondo All rights reserved

79/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

struct Exit :msm::front::exit_pseudo_state<msmf::none> {};

exit point疑似状態

exit point 疑似状態の実装

伝搬イベント無し

state

Copyright 2011 Takatoshi Kondo All rights reserved

80/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

struct AccountInfo { AccountInfo(int amount_):balance(amount_) {} int balance; };

サブStateMachineからの情報の伝搬

伝搬する情報

event

struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < AuthExitSuccess, AccountInfo, EnteringAmount, SetAccountInfo, msmf::none >,

遷移

struct SetAccountInfo { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const& e, Fsm&, SourceState&, TargetState& t) const { t.info = e; } };

action

eventは無いが

eventとして記述

サブStateMachineからexit_successする際に自動でイベントが発生する

struct EnteringAmount:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Input amount of money" << std::endl; } EnteringAmount():amount(0), info(0) {} int amount; AccountInfo info; };

state

stateに口座情報を持たせる

口座情報を設定する

Copyright 2011 Takatoshi Kondo All rights reserved

81/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < EnteringAmount, EnterAmount, msmf::none, SetAmount, msmf::none >,

内部遷移

内部遷移の実装

struct SetAmount { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const& e, Fsm&, SourceState&, TargetState& t) const { t.amount = e.amount; } };

struct EnterAmount { EnterAmount(int amount_):amount(amount_) {} int amount; };

struct EnteringAmount:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Input amount of money" << std::endl; } EnteringAmount():amount(0), info(0) {} int amount; AccountInfo info; };

Nextをnoneに設定すれば内部遷移となる

state

event

遷移

action

stateが持つ情報を更新

stateに引き出し金額情報を持たせる

Copyright 2011 Takatoshi Kondo All rights reserved

82/95

ATM(引き出し)

include / 生体認証

金額入力中

entry/ 金額入力画面表示, 金額初期化 数字ボタン押下/ 金額更新

認証中

entry

exit_success

exit_fail

キャンセルボタン押下

[金額 <= アカウント情報.残高] / 支払い, 残高更新 [else]

確認ボタン押下

残高不足提示中

entry/ 残高不足画面表示

確認ボタン押下

引き出し

カード挿入待ち

entry / カード要求画面提示 カード挿入

entry

entry_by_card

残高提示中

entry/ 残高画面表示

確認ボタン押下

exit

アカウント情報

struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < EnteringAmount, Ok, InsufficientFunds, msmf::none, msmf::none >, /*else*/ msmf::Row < EnteringAmount, Ok, DisplayingBalance, Pay, CheckAmount >, msmf::Row < EnteringAmount, EnterAmount, msmf::none, SetAmount, msmf::none >,

if/else分岐

if/else分岐の実装

遷移

struct CheckAmount { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState& s, TargetState&) const { return s.amount <= s.info.balance; } };

guard

遷移評価順序が下から上であることを利用

サブStateMachineから伝搬させて設定済み

Copyright 2011 Takatoshi Kondo All rights reserved

83/95

#include "atm_account_info.hpp" #include "atm_card_detect.hpp" namespace Atm { struct Cancel {}; struct Ok {}; struct EnterAmount { EnterAmount(int amount_):amount(amount_) {} int amount; }; template <class AuthMethod> struct Withdraw_:msm::front::state_machine_def<Withdraw_<AuthMethod> > { struct Entry :msm::front::entry_pseudo_state<> {}; struct EntryByCard:msm::front::entry_pseudo_state<> {}; struct Exit :msm::front::exit_pseudo_state<msmf::none> {}; struct WaitingCard:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Please insert your card" << std::endl; } }; struct WithdrawAuth:AuthMethod {}; struct EnteringAmount:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Input amount of money" << std::endl; } EnteringAmount():amount(0), info(0) {} int amount; AccountInfo info; };

ATM(引き出し)

Copyright 2011 Takatoshi Kondo All rights reserved

84/95

struct InsufficientFunds:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Insufficient Funds" << std::endl; } }; struct DisplayingBalance:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Your balance:" << balance << std::endl; } void setBalance(int balance_) { balance = balance_; } int balance; }; struct CheckAmount { template <class Event, class Fsm, class SourceState, class TargetState> bool operator()(Event const&, Fsm&, SourceState& s, TargetState&) const { return s.amount <= s.info.balance; } }; struct SetAccountInfo { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const& e, Fsm&, SourceState&, TargetState& t) const { t.info = e; } };

ATM(引き出し)

Copyright 2011 Takatoshi Kondo All rights reserved

85/95

struct SetAmount { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const& e, Fsm&, SourceState&, TargetState& t) const { t.amount = e.amount; } }; struct Pay { template <class Event, class Fsm, class SourceState, class TargetState> void operator()(Event const&, Fsm&, SourceState& s, TargetState& t) const { t.setBalance(s.info.balance - s.amount); } }; typedef Entry initial_state; typedef typename WithdrawAuth::template entry_pt<typename AuthMethod::Derived::Entry> AuthEntry; typedef typename WithdrawAuth::template exit_pt <typename AuthMethod::Derived::ExitFail> AuthExitFail; typedef typename WithdrawAuth::template exit_pt <typename AuthMethod::Derived::ExitSuccess> AuthExitSuccess; // Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < AuthExitSuccess, AccountInfo, EnteringAmount, SetAccountInfo, msmf::none >, msmf::Row < EnteringAmount, Ok, InsufficientFunds, msmf::none, msmf::none >, /*else*/ msmf::Row < EnteringAmount, Ok, DisplayingBalance, Pay, CheckAmount >, msmf::Row < EnteringAmount, EnterAmount, msmf::none, SetAmount, msmf::none >, msmf::Row < InsufficientFunds, Ok, EnteringAmount, msmf::none, msmf::none >, msmf::Row < DisplayingBalance, Ok, Exit, msmf::none, msmf::none > > {}; }; template <class AuthMethod> struct Withdraw:msm::back::state_machine<Withdraw_<AuthMethod> > {}; }

ATM(引き出し)

Copyright 2011 Takatoshi Kondo All rights reserved

86/95

ATM(認証) entry

exit_success

exit_fail

指検出

認証失敗

認証成功(アカウント情報)

生体認証

認証中

entry/認証中画面提示, 認証開始

指待ち

entry/指要求画面提示

タイムアウト

アカウント情報

Copyright 2011 Takatoshi Kondo All rights reserved

87/95

ATM(認証) entry

exit_success

exit_fail

指検出

認証失敗

認証成功(アカウント情報)

生体認証

認証中

entry/認証中画面提示, 認証開始

指待ち

entry/指要求画面提示

タイムアウト

アカウント情報

struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Checking, AuthSuccess, ExitSuccess, msmf::none, msmf::none >,

struct ExitSuccess :msm::front::exit_pseudo_state<AccountInfo> {}; state

遷移

伝搬させたい情報

struct AuthSuccess:AccountInfo { AuthSuccess(AccountInfo const& info):AccountInfo(info) {} };

event

struct AccountInfo { AccountInfo(int amount_):balance(amount_) {} int balance; };

event

Copyright 2011 Takatoshi Kondo All rights reserved

88/95

ATM (認証)

#include "atm_account_info.hpp" namespace Atm { struct AuthSuccess; struct AuthSuccess:AccountInfo { AuthSuccess(AccountInfo const& info):AccountInfo(info) {} }; struct AuthFail {}; struct AuthTimeout {}; struct FingerDetect {}; struct BioAuth_:msm::front::state_machine_def<BioAuth_> { struct Entry :msm::front::entry_pseudo_state<> {}; struct ExitSuccess :msm::front::exit_pseudo_state<AccountInfo> {}; struct ExitFail :msm::front::exit_pseudo_state<msmf::none> {}; struct WaitingFinger:msm::front::state<> { template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Please place your finger on the sensor" << std::endl; } }; struct Checking:msm::front::state<> { // Entry action template <class Event,class Fsm> void on_entry(Event const&, Fsm&) const { std::cout << "Now checking" << std::endl; } }; typedef Entry initial_state; struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Entry, msmf::none, WaitingFinger, msmf::none, msmf::none >, msmf::Row < WaitingFinger, FingerDetect, Checking, msmf::none, msmf::none >, msmf::Row < WaitingFinger, AuthTimeout, ExitFail, msmf::none, msmf::none >, msmf::Row < Checking, AuthSuccess, ExitSuccess, msmf::none, msmf::none >, msmf::Row < Checking, AuthFail, ExitFail, msmf::none, msmf::none > > {}; }; typedef msm::back::state_machine<BioAuth_> BioAuth; }

Copyright 2011 Takatoshi Kondo All rights reserved

89/95

Client – int main() #include "atm_all.hpp" #include "atm_bio_auth.hpp" int main() { Atm::All<Atm::BioAuth> t; t.start(); t.process_event(Atm::HumanDetect()); t.process_event(Atm::ChooseWithdraw()); t.process_event(Atm::CardDetect()); t.process_event(Atm::FingerDetect()); t.process_event(Atm::AuthSuccess(Atm::AccountInfo(100))); t.process_event(Atm::EnterAmount(50)); t.process_event(Atm::Ok()); t.process_event(Atm::Ok()); }

StateMachineのインスタンス宣言・定義

StateMachineの開始

eventの発行

initial_stateのentry actionは ここで実行される

Copyright 2011 Takatoshi Kondo All rights reserved

90/95

Client StateMachine 共通event

依存関係 ~include関係

main.cpp

atm_account_info.hpp

atm_all.hpp

atm_bio_auth.hpp

atm_card_detect.hpp

atm_trade.hpp

atm_withdraw.hpp

withdrawのサブStateMachine としてbio_authを利用しているが

includeは不要

Copyright 2011 Takatoshi Kondo All rights reserved

91/95

Client StateMachine 共通event

依存関係

main.cpp

atm_account_info.hpp

atm_all.hpp

atm_bio_auth.hpp

atm_card_detect.hpp

atm_trade.hpp

atm_withdraw.hpp

親StateMachineを意識しない

親StateMachineを意識しない

暗黙の依存 インターフェースを意識するが、 ファイルはincludeしない

状態マシンを部品としてライブラリ的に再利用可能 フレームワークとしての利用も可能

Copyright 2011 Takatoshi Kondo All rights reserved

92/95

Boost.MSMのUML2.x要素対応

初期疑似状態 Initial Pseudo State

終了状態 Final State

ジャンクション疑似状態 Junction Pseudo State

選択疑似状態 Choice Pseudo State

State entry point疑似状態 Entry Point Pseudo State

exit point疑似状態 Exit Point Pseudo State

H

H *

shallow history

deep history

initial_state の typedef

terminate_state または、 exit_pseudo_state

手作業で等価変換することで対応

(普通の)state と anonymous transition + guardで対応

entry_pseudo_state

exit_pseudo_state (event伝搬拡張あり)

AlwaysHistoryで対応(event限定拡張あり)

対応予定無し UMLでの並行状態における意味が曖昧

StateMachine図(UML2.x)要素 Boost.MSMでの対応

Sub Machine State state_machine_def で対応

Copyright 2011 Takatoshi Kondo All rights reserved

93/95

Boost.MSMのUML2.x要素対応 StateMachine図(UML2.x)要素 Boost.MSMでの対応

並行状態 State

initial_state の typedef を mpl::vectorとすることで対応

fork

forkノード entry_pseudo_state にインデックスを指定することで対応 explicit_entryによっても対応可能

join

joinノード 待ち合わせ状態を作り、StateMachineにカウンタなどを 持たせることで対応可能

eventのdefer (延期) activate_deferred_events typedefの 遷移アクション Deferで対応可能

Actionでの自身へのeventを発行 fsm.proccess_event(event)を呼び出すことで対応 ※キューイング処理され、再帰が連鎖することはない

Copyright 2011 Takatoshi Kondo All rights reserved

94/95

Boost.Msmの使い方

Copyright 2011 Takatoshi Kondo All rights reserved

95/95