player1.cpp

来自「Boost provides free peer-reviewed portab」· C++ 代码 · 共 288 行

CPP
288
字号
/*    Copyright David Abrahams 2003-2004    Copyright Aleksey Gurtovoy 2003-2004    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)                This file was automatically extracted from the source of     "C++ Template Metaprogramming", by David Abrahams and     Aleksey Gurtovoy.    It was built successfully with GCC 3.4.2 on Windows using    the following command:         g++ -I..\..\boost_1_32_0  -o%TEMP%\metaprogram-chapter11-example16.exe example16.cpp        */#include <boost/mpl/fold.hpp>#include <boost/mpl/filter_view.hpp>#include <boost/type_traits/is_same.hpp>#include <vector>#include <ctime>#include <boost/mpl/vector.hpp>#include <boost/mpl/placeholders.hpp>#include <boost/mpl/assert.hpp>#include <boost/static_assert.hpp>namespace mpl = boost::mpl;using namespace mpl::placeholders;#include <cassert>template<    class Transition  , class Next>struct event_dispatcher{    typedef typename Transition::fsm_t fsm_t;    typedef typename Transition::event event;    static int dispatch(        fsm_t& fsm, int state, event const& e)    {        if (state == Transition::current_state)        {            Transition::execute(fsm, e);            return Transition::next_state;        }        else // move on to the next node in the chain.        {            return Next::dispatch(fsm, state, e);        }    }};template <class Derived> class state_machine;struct default_event_dispatcher{    template<class FSM, class Event>    static int dispatch(        state_machine<FSM>& m, int state, Event const& e)    {        return m.call_no_transition(state, e);    }};    template<class Table, class Event>    struct generate_dispatcher;template<class Derived>class state_machine{    // ... protected:    template<        int CurrentState      , class Event      , int NextState      , void (Derived::*action)(Event const&)    >    struct row    {        // for later use by our metaprogram        static int const current_state = CurrentState;        static int const next_state = NextState;        typedef Event event;        typedef Derived fsm_t;        // do the transition action.        static void execute(Derived& fsm, Event const& e)        {            (fsm.*action)(e);        }    };        friend class default_event_dispatcher;        template <class Event>    int call_no_transition(int state, Event const& e)    {        return static_cast<Derived*>(this)  // CRTP downcast                   ->no_transition(state, e);    }    // public:template<class Event>int process_event(Event const& evt){    // generate the dispatcher type.    typedef typename generate_dispatcher<        typename Derived::transition_table, Event    >::type dispatcher;    // dispatch the event.    this->state = dispatcher::dispatch(        *static_cast<Derived*>(this)        // CRTP downcast      , this->state      , evt    );    // return the new state    return this->state;}// ... protected:    state_machine()      : state(Derived::initial_state)    {    } private:    int state;// ...// ... public:    template <class Event>    int no_transition(int state, Event const& e)    {        assert(false);        return state;    }// ...////  };// get the Event associated with a transition.template <class Transition>struct transition_event{    typedef typename Transition::event type;};template<class Table, class Event>struct generate_dispatcher  : mpl::fold<        mpl::filter_view<   // select rows triggered by Event            Table          , boost::is_same<Event, transition_event<_1> >        >      , default_event_dispatcher      , event_dispatcher<_2,_1>     >{};  struct play {};  struct open_close {};  struct cd_detected {     cd_detected(char const*, std::vector<std::clock_t> const&) {}  };  #ifdef __GNUC__ // in which pause seems to have a predefined meaning  # define pause pause_  #endif  struct pause {};  struct stop {};  // concrete FSM implementation class player : public state_machine<player>{ private:    // the list of FSM states    enum states {        Empty, Open, Stopped, Playing, Paused      , initial_state = Empty    };        #ifdef __MWERKS__     public: // Codewarrior bug workaround.  Tested at 0x3202    #endif        void start_playback(play const&);    void open_drawer(open_close const&);    void close_drawer(open_close const&);    void store_cd_info(cd_detected const&);    void stop_playback(stop const&);    void pause_playback(pause const&);    void resume_playback(play const&);    void stop_and_open(open_close const&);        #ifdef __MWERKS__       private:    #endif           friend class state_machine<player>;    typedef player p; // makes transition table cleaner    // transition table    struct transition_table : mpl::vector11<    //    Start     Event         Next      Action    //  +---------+-------------+---------+---------------------+    row < Stopped , play        , Playing , &p::start_playback  >,    row < Stopped , open_close  , Open    , &p::open_drawer     >,    //  +---------+-------------+---------+---------------------+    row < Open    , open_close  , Empty   , &p::close_drawer    >,    //  +---------+-------------+---------+---------------------+    row < Empty   , open_close  , Open    , &p::open_drawer     >,    row < Empty   , cd_detected , Stopped , &p::store_cd_info   >,    //  +---------+-------------+---------+---------------------+    row < Playing , stop        , Stopped , &p::stop_playback   >,    row < Playing , pause       , Paused  , &p::pause_playback  >,    row < Playing , open_close  , Open    , &p::stop_and_open   >,    //  +---------+-------------+---------+---------------------+    row < Paused  , play        , Playing , &p::resume_playback >,    row < Paused  , stop        , Stopped , &p::stop_playback   >,    row < Paused  , open_close  , Open    , &p::stop_and_open   >    //  +---------+-------------+---------+---------------------+    > {};typedef event_dispatcher<    row<Stopped, play, Playing, &player::start_playback>  , event_dispatcher<        row<Paused, play, Playing, &player::resume_playback>      , default_event_dispatcher    >> dummy;};  void player::start_playback(play const&){}  void player::open_drawer(open_close const&){}  void player::close_drawer(open_close const&){}  void player::store_cd_info(cd_detected const&){}  void player::stop_playback(stop const&){}  void player::pause_playback(pause const&){}  void player::resume_playback(play const&){}  void player::stop_and_open(open_close const&){}  int main(){    player p;                      // An instance of the FSM    p.process_event(open_close()); // user opens CD player    p.process_event(open_close()); // inserts CD and closes    p.process_event(               // CD is detected        cd_detected(             "louie, louie"           , std::vector<std::clock_t>( /* track lengths */ )        )    );    p.process_event(play());       // etc.    p.process_event(pause());    p.process_event(play());    p.process_event(stop());    return 0;}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?