// Copyright 2010 Christophe Henry // henry UNDERSCORE christophe AT hotmail DOT com // This is an extended version of the state machine available in the boost::mpl library // Distributed under the same license as the original. // Copyright for the original version: // Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed // under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at // http://www.boost.org/LICENSE_1_0.txt) #include #include #include #include #include "boost/mpl/list.hpp" #include #include #ifdef WIN32 #include "windows.h" #else #include #endif namespace sc = boost::statechart; namespace mpl = boost::mpl; namespace test_sc { //events struct play : sc::event< play > {}; struct end_pause : sc::event< end_pause > {}; struct stop : sc::event< stop > {}; struct pause : sc::event< pause > {}; struct open_close : sc::event< open_close > {}; struct cd_detected : sc::event< cd_detected > {}; struct NextSong: sc::event< NextSong > {}; struct PreviousSong : sc::event< PreviousSong >{}; struct Empty; struct Open; struct Stopped; struct Playing; struct Paused; // SM struct player : sc::state_machine< player, Empty > { void open_drawer(open_close const&) { /*std::cout << "player::open_drawer\n";*/ } void store_cd_info(cd_detected const& cd) {/*std::cout << "player::store_cd_info\n";*/ } void close_drawer(open_close const&) { /*std::cout << "player::close_drawer\n";*/ } void start_playback(play const&) { /*std::cout << "player::start_playback\n";*/ } void stopped_again(stop const&) {/*std::cout << "player::stopped_again\n";*/} void stop_playback(stop const&) { /*std::cout << "player::stop_playback\n";*/ } void pause_playback(pause const&) { /*std::cout << "player::pause_playback\n"; */} void stop_and_open(open_close const&) { /*std::cout << "player::stop_and_open\n";*/ } void resume_playback(end_pause const&) { /*std::cout << "player::resume_playback\n";*/ } }; struct Empty : sc::simple_state< Empty, player > { Empty() { /*std::cout << "entering Empty" << std::endl;*/ } // entry ~Empty() { /*std::cout << "leaving Empty" << std::endl;*/ } // exit typedef mpl::list< sc::transition< open_close, Open, player, &player::open_drawer >, sc::transition< cd_detected, Stopped, player, &player::store_cd_info > > reactions; }; struct Open : sc::simple_state< Open, player > { Open() { /*std::cout << "entering Open" << std::endl;*/ } // entry ~Open() { /*std::cout << "leaving Open" << std::endl;*/ } // exit typedef sc::transition< open_close, Empty, player, &player::close_drawer > reactions; }; struct Stopped : sc::simple_state< Stopped, player > { Stopped() { /*std::cout << "entering Stopped" << std::endl;*/ } // entry ~Stopped() { /*std::cout << "leaving Stopped" << std::endl;*/ } // exit typedef mpl::list< sc::transition< play, Playing, player, &player::start_playback >, sc::transition< open_close, Open, player, &player::open_drawer >, sc::transition< stop, Stopped, player, &player::stopped_again > > reactions; }; struct Song1; struct Playing : sc::simple_state< Playing, player,Song1 > { Playing() { /*std::cout << "entering Playing" << std::endl;*/ } // entry ~Playing() { /*std::cout << "leaving Playing" << std::endl;*/ } // exit typedef mpl::list< sc::transition< stop, Stopped, player, &player::stop_playback >, sc::transition< pause, Paused, player, &player::pause_playback >, sc::transition< open_close, Open, player, &player::stop_and_open > > reactions; void start_next_song(NextSong const&) { /*std::cout << "Playing::start_next_song\n";*/ } void start_prev_song(PreviousSong const&) { /*std::cout << "Playing::start_prev_song\n";*/ } }; struct Song2; struct Song1 : sc::simple_state< Song1, Playing > { Song1() { /*std::cout << "entering Song1" << std::endl;*/ } // entry ~Song1() { /*std::cout << "leaving Song1" << std::endl;*/ } // exit typedef sc::transition< NextSong, Song2, Playing, &Playing::start_next_song > reactions; }; struct Song3; struct Song2 : sc::simple_state< Song2, Playing > { Song2() { /*std::cout << "entering Song2" << std::endl;*/ } // entry ~Song2() { /*std::cout << "leaving Song2" << std::endl;*/ } // exit typedef mpl::list< sc::transition< NextSong, Song3, Playing, &Playing::start_next_song >, sc::transition< PreviousSong, Song1, Playing, &Playing::start_prev_song > > reactions; }; struct Song3 : sc::simple_state< Song3, Playing > { Song3() { /*std::cout << "entering Song3" << std::endl;*/ } // entry ~Song3() { /*std::cout << "leaving Song3" << std::endl;*/ } // exit typedef sc::transition< PreviousSong, Song2, Playing, &Playing::start_prev_song > reactions; }; struct Paused : sc::simple_state< Paused, player > { Paused() { /*std::cout << "entering Paused" << std::endl;*/ } // entry ~Paused() { /*std::cout << "leaving Paused" << std::endl;*/ } // exit typedef mpl::list< sc::transition< end_pause, Playing, player, &player::resume_playback >, sc::transition< stop, Stopped, player, &player::stop_playback >, sc::transition< open_close, Open, player, &player::stop_and_open > > reactions; }; } #ifndef WIN32 long mtime(struct timeval& tv1,struct timeval& tv2) { return (tv2.tv_sec-tv1.tv_sec) *1000000 + ((tv2.tv_usec-tv1.tv_usec)); } #endif int main() { test_sc::player p; p.initiate(); // for timing #ifdef WIN32 LARGE_INTEGER res; ::QueryPerformanceFrequency(&res); LARGE_INTEGER li,li2; ::QueryPerformanceCounter(&li); #else struct timeval tv1,tv2; gettimeofday(&tv1,NULL); #endif for (int i=0;i<100;++i) { p.process_event(test_sc::open_close()); p.process_event(test_sc::open_close()); p.process_event(test_sc::cd_detected()); p.process_event(test_sc::play()); for (int j=0;j<100;++j) { p.process_event(test_sc::NextSong()); p.process_event(test_sc::NextSong()); p.process_event(test_sc::PreviousSong()); p.process_event(test_sc::PreviousSong()); } p.process_event(test_sc::pause()); // go back to Playing p.process_event(test_sc::end_pause()); p.process_event(test_sc::pause()); p.process_event(test_sc::stop()); // event leading to the same state p.process_event(test_sc::stop()); p.process_event(test_sc::open_close()); p.process_event(test_sc::open_close()); } #ifdef WIN32 ::QueryPerformanceCounter(&li2); #else gettimeofday(&tv2,NULL); #endif #ifdef WIN32 std::cout << "sc took in s:" << (double)(li2.QuadPart-li.QuadPart)/res.QuadPart <<"\n" <