#include #include #include #include namespace { namespace msm = boost::msm; namespace msmf = boost::msm::front; namespace mpl = boost::mpl; // ----- Events struct AnyEvent {}; struct StartButtonPressed:AnyEvent {}; struct CheckSucceeded {}; struct CheckFailed {}; struct ScanSucceeded {}; struct ScanFailed {}; struct Completed:AnyEvent { enum Result { OK, NG }; Completed(CheckFailed const&):r_(NG) {} Completed(ScanSucceeded const&):r_(OK) {} Completed(ScanFailed const&):r_(NG) {} Result result() const { return r_; } private: Result r_; }; // ----- State machine struct Sm1_:msmf::state_machine_def { struct Waiting_:msmf::state<> { template void on_entry(Event const&, Fsm&) const { std::cout << "Press Start Button" << std::endl; } }; struct ScanFinger_:msmf::state_machine_def { struct AliveChecking:msmf::state<> { template void on_entry(Event const&, Fsm&) const { std::cout << "Alive checking..." << std::endl; } }; struct Scanning:msmf::state<> { template void on_entry(Event const&, Fsm&) const { std::cout << "Scanning..." << std::endl; } }; struct Entry1:msmf::entry_pseudo_state<> {}; struct Exit1:msmf::exit_pseudo_state {}; // Set initial state typedef mpl::vector initial_state; // Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < AliveChecking, CheckSucceeded, Scanning, msmf::none, msmf::none >, msmf::Row < AliveChecking, CheckFailed, Exit1, msmf::none, msmf::none >, msmf::Row < Entry1, AnyEvent, Scanning, msmf::none, msmf::none >, msmf::Row < Scanning, ScanSucceeded, Exit1, msmf::none, msmf::none >, msmf::Row < Scanning, ScanFailed, Exit1, msmf::none, msmf::none > > {}; }; struct RightScanning_:ScanFinger_ {}; struct LeftScanning_:ScanFinger_ {}; typedef msm::back::state_machine RightScanning; typedef msm::back::state_machine LeftScanning; // Actions struct RightMessage { template void operator()(Event const&, Fsm&, SourceState&, TargetState&) { std::cout << "Right hand please." << std::endl; } }; struct LeftMessage { template void operator()(Event const&, Fsm&, SourceState&, TargetState&) { std::cout << "Left hand please." << std::endl; } }; struct FailMessage { template void operator()(Event const&, Fsm&, SourceState&, TargetState&) { std::cout << "Register Failed." << std::endl; } }; struct CompleteMessage { template void operator()(Event const&, Fsm&, SourceState&, TargetState&) { std::cout << "Register Completed." << std::endl; } }; // Guards struct IsResultOk { template bool operator()(Event const& e, Fsm&, SourceState&, TargetState&) { return e.result() == Completed::OK; } }; // Set initial state typedef Waiting_ initial_state; // Transition table struct transition_table:mpl::vector< // Start Event Next Action Guard msmf::Row < Waiting_, StartButtonPressed, RightScanning::entry_pt , RightMessage, msmf::none >, msmf::Row < RightScanning::exit_pt , Completed, Waiting_, FailMessage, msmf::none >, // else msmf::Row < RightScanning::exit_pt , Completed, LeftScanning::entry_pt , LeftMessage, IsResultOk >, msmf::Row < LeftScanning::exit_pt , Completed, Waiting_, FailMessage, msmf::none >, // else msmf::Row < LeftScanning::exit_pt , Completed, Waiting_, CompleteMessage, IsResultOk > > {}; }; // Pick a back-end typedef msm::back::state_machine Sm1; void test() { Sm1 sm1; sm1.start(); std::cout << "=== 1. Success Scenario ===" << std::endl; std::cout << "> Send StartButtonPressed()" << std::endl; sm1.process_event(StartButtonPressed()); std::cout << "> Send ScanSucceeded()" << std::endl; sm1.process_event(ScanSucceeded()); std::cout << "> Send ScanSucceeded()" << std::endl; sm1.process_event(ScanSucceeded()); std::cout << "=== 2. Right Fail Scenario ===" << std::endl; std::cout << "> Send StartButtonPressed()" << std::endl; sm1.process_event(StartButtonPressed()); std::cout << "> Send ScanFailed()" << std::endl; sm1.process_event(ScanFailed()); std::cout << "=== 3. Left Fail Scenario ===" << std::endl; std::cout << "> Send StartButtonPressed()" << std::endl; sm1.process_event(StartButtonPressed()); std::cout << "> Send ScanSucceeded()" << std::endl; sm1.process_event(ScanSucceeded()); std::cout << "> Send ScanFailed()" << std::endl; sm1.process_event(ScanFailed()); } } int main() { test(); return 0; } // Output: // // Press Start Button // === 1. Success Scenario === // > Send StartButtonPressed() // Right hand please. // Scanning... // > Send ScanSucceeded() // Left hand please. // Scanning... // > Send ScanSucceeded() // Register Completed. // Press Start Button // === 2. Right Fail Scenario === // > Send StartButtonPressed() // Right hand please. // Scanning... // > Send ScanFailed() // Register Failed. // Press Start Button // === 3. Left Fail Scenario === // > Send StartButtonPressed() // Right hand please. // Scanning... // > Send ScanSucceeded() // Left hand please. // Scanning... // > Send ScanFailed() // Register Failed. // Press Start Button