diff --git a/example/fsm/aux_/STT_impl_gen.hpp b/example/fsm/aux_/STT_impl_gen.hpp new file mode 100644 index 0000000..d6c0ccf --- /dev/null +++ b/example/fsm/aux_/STT_impl_gen.hpp @@ -0,0 +1,150 @@ +//----------------------------------------------------------------------------- +// boost fsm/handler.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_FSM_HANDLER_INCLUDED +#define BOOST_FSM_HANDLER_INCLUDED + +#include "boost/mpl/if.hpp" +#include "boost/mpl/fold.hpp" +#include "boost/mpl/front.hpp" +#include "boost/type_traits/is_same.hpp" + +#include +#include + +namespace fsm { +namespace aux { + +namespace mpl = boost::mpl; +using namespace mpl::placeholder; + +template< typename Transition > +struct STT_void_row_impl +{ + typedef typename Transition::from_state_t state_t; + typedef typename Transition::fsm_t fsm_t; + typedef typename Transition::base_event_t base_event_t; + + static long do_process_event(fsm_t&, long state, base_event_t const&) + { + assert(false); + return state; + } + + static long do_transition(fsm_t&, long state, base_event_t const&) + { + assert(false); + return state; + } +}; + + +template< + typename PrevRowImpl + , typename Transition + > +struct STT_event_row_impl + : PrevRowImpl +{ + typedef typename Transition::from_state_t state_t; + typedef typename Transition::fsm_t fsm_t; + typedef typename Transition::base_event_t base_event_t; + + static long do_process_event(fsm_t& fsm, long state, base_event_t const& evt) + { + if (typeid(typename Transition::event_t) == typeid(evt)) + { + // typedefs are here to make GCC happy + typedef typename Transition::to_state_t to_state_; + typedef typename Transition::from_state_t from_state_; + + return Transition::do_transition(fsm, evt) + ? to_state_::do_check_invariant(fsm) + : from_state_::do_check_invariant(fsm) + ; + } + + return PrevRowImpl::do_process_event(fsm, state, evt); + } +}; + +template< + typename PrevRowImpl + , typename StateType + > +struct STT_state_row_impl + : PrevRowImpl +{ + typedef typename PrevRowImpl::fsm_t fsm_t; + typedef typename PrevRowImpl::base_event_t base_event_t; + + static long do_transition(fsm_t& fsm, long state, base_event_t const& evt) + { + return state == StateType::value + ? PrevRowImpl::do_process_event(fsm, state, evt) + : PrevRowImpl::do_transition(fsm, state, evt) + ; + } + + static long do_process_event(fsm_t&, long state, base_event_t const&) + { + assert(false); + return state; + } +}; + +template< + typename PrevRowImpl + , typename Transition + > +struct STT_row_impl +{ + typedef typename mpl::if_< + boost::is_same< + typename PrevRowImpl::state_t + , typename Transition::from_state_t + > + , STT_event_row_impl< PrevRowImpl,Transition > + , STT_event_row_impl< + STT_state_row_impl< PrevRowImpl,typename PrevRowImpl::state_t > + , Transition + > + >::type type; +}; + + +template< typename Transitions > +struct STT_impl_gen +{ + private: + typedef typename mpl::front::type first_; + typedef typename mpl::fold< + Transitions + , STT_void_row_impl + , STT_row_impl<_,_> + >::type STT_impl_; + + public: + typedef STT_state_row_impl< + STT_impl_ + , typename STT_impl_::state_t + > type; +}; + +} // namespace aux +} // namespace fsm + +#endif // BOOST_FSM_HANDLER_INCLUDED diff --git a/example/fsm/aux_/base_event.hpp b/example/fsm/aux_/base_event.hpp new file mode 100644 index 0000000..a0c007c --- /dev/null +++ b/example/fsm/aux_/base_event.hpp @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// boost fsm/base_event.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_FSM_BASE_EVENT_INCLUDED +#define BOOST_FSM_BASE_EVENT_INCLUDED + +#include + +namespace fsm { +namespace aux { + +// represent an abstract base for FSM events + +struct base_event +{ + public: + virtual ~base_event() {}; + + std::auto_ptr clone() const + { + return do_clone(); + } + + private: + virtual std::auto_ptr do_clone() const = 0; +}; + +} // namespace aux +} // namespace fsm + +#endif // BOOST_FSM_BASE_EVENT_INCLUDED diff --git a/example/fsm/aux_/event.hpp b/example/fsm/aux_/event.hpp new file mode 100644 index 0000000..4961e19 --- /dev/null +++ b/example/fsm/aux_/event.hpp @@ -0,0 +1,44 @@ +//----------------------------------------------------------------------------- +// boost fsm/event.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_FSM_EVENT_INCLUDED +#define BOOST_FSM_EVENT_INCLUDED + +#include "base_event.hpp" + +namespace fsm { +namespace aux { + +template< typename Derived > +struct event + : base_event +{ + public: + typedef base_event base_t; + + private: + virtual std::auto_ptr do_clone() const + { + return std::auto_ptr( + new Derived(static_cast(*this)) + ); + } +}; + +} // namespace aux +} // namespace fsm + +#endif // BOOST_FSM_EVENT_INCLUDED diff --git a/example/fsm/aux_/state.hpp b/example/fsm/aux_/state.hpp new file mode 100644 index 0000000..462e62a --- /dev/null +++ b/example/fsm/aux_/state.hpp @@ -0,0 +1,47 @@ +//----------------------------------------------------------------------------- +// boost fsm/state.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_FSM_STATE_INCLUDED +#define BOOST_FSM_STATE_INCLUDED + +#include "boost/mpl/integral_c.hpp" + +namespace fsm { +namespace aux { + +namespace mpl = boost::mpl; + +// represent a FSM state + +template< + typename T + , long State + , void (T::* invariant_func)() const + > +struct state + : mpl::integral_c +{ + static long do_check_invariant(T const& x) + { + if (invariant_func) (x.*invariant_func)(); + return State; + } +}; + +} // namespace aux +} // namespace fsm + +#endif // BOOST_FSM_STATE_INCLUDED diff --git a/example/fsm/aux_/transition.hpp b/example/fsm/aux_/transition.hpp new file mode 100644 index 0000000..cf7855f --- /dev/null +++ b/example/fsm/aux_/transition.hpp @@ -0,0 +1,52 @@ +//----------------------------------------------------------------------------- +// boost fsm/transition.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_FSM_TRANSITION_INCLUDED +#define BOOST_FSM_TRANSITION_INCLUDED + +#include + +namespace fsm { +namespace aux { + +// represent a signle transition between states |From| and |To| + +template< + typename T + , typename From + , typename Event + , typename To + , bool (T::* transition_func)(Event const&) + > +struct transition +{ + typedef T fsm_t; + typedef From from_state_t; + typedef Event event_t; + typedef To to_state_t; + + typedef typename Event::base_t base_event_t; + static bool do_transition(T& x, base_event_t const& e) + { + assert(dynamic_cast(&e) == &e); + return (x.*transition_func)(static_cast(e)); + } +}; + +} // namespace aux +} // namespace fsm + +#endif // BOOST_FSM_TRANSITION_INCLUDED diff --git a/example/fsm/player.cpp b/example/fsm/player.cpp new file mode 100644 index 0000000..5b4886f --- /dev/null +++ b/example/fsm/player.cpp @@ -0,0 +1,79 @@ +//----------------------------------------------------------------------------- +// boost fsm/example/player.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#include "state_machine.hpp" +#include "boost/mpl/list.hpp" + +#include + +namespace mpl = boost::mpl; + +class player + : public fsm::state_machine +{ + public: + player() {} + + // events + struct play_event : event {}; + struct stop_event : event {}; + struct pause_event : event {}; + +// MWCW 8.1 is too eager in inforcing access for non-type template parameters +// private: + typedef player self_t; + + // state invariants + void stopped_state_invariant() const {} + void playing_state_invariant() const {} + void paused_state_invariant() const {} + + // states (invariants are passed as non-type template arguments) + typedef state<0, &self_t::stopped_state_invariant> stopped; + typedef state<1, &self_t::playing_state_invariant> playing; + typedef state<2, &self_t::paused_state_invariant> paused; + +// private: + + // transition functions + bool do_play(play_event const&) { std::cout << "player::do_play\n"; return true; } + bool do_stop(stop_event const&) { std::cout << "player::do_stop\n"; return true; } + bool do_pause(pause_event const&) { std::cout << "player::do_pause\n"; return true; } + bool do_resume(play_event const&) { std::cout << "player::do_resume\n"; return true; } + + // transitions, in the following format: + // | current state | event | next state | transition function | + friend class fsm::state_machine; + typedef mpl::list< + transition + , transition + , transition + , transition + , transition + >::type transition_table; + + typedef stopped initial_state; +}; + +int main() +{ + player p; + p.process_event(player::play_event()); + p.process_event(player::pause_event()); + p.process_event(player::play_event()); + p.process_event(player::stop_event()); + return 0; +} diff --git a/example/fsm/state_machine.hpp b/example/fsm/state_machine.hpp new file mode 100644 index 0000000..baa28af --- /dev/null +++ b/example/fsm/state_machine.hpp @@ -0,0 +1,133 @@ +//----------------------------------------------------------------------------- +// boost fsm/state_machine.hpp header file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#ifndef BOOST_FSM_STATE_MACHINE_INCLUDED +#define BOOST_FSM_STATE_MACHINE_INCLUDED + +#include "aux_/event.hpp" +#include "aux_/state.hpp" +#include "aux_/transition.hpp" +#include "aux_/STT_impl_gen.hpp" +#include "boost/shared_ptr.hpp" + +#include +#include +#include + +namespace fsm { + +template< typename Derived > +class state_machine +{ + private: + typedef state_machine self_t; + typedef aux::base_event base_event_t; + typedef boost::shared_ptr base_event_ptr_t; + + public: + typedef long state_t; + + template< typename DerivedEvent > + struct event + : aux::event + { + }; + + void process_event(base_event_t const& evt) + { + // all internal events should be handled at this point + assert(!m_events_queue.size()); + + // process the external event passed + do_transition(evt); + + // if the previous transition generated any internal events, + // process those + while (m_events_queue.size()) + { + do_transition(*m_events_queue.front()); + m_events_queue.pop(); + } + } + + state_t current_state() const + { + return m_state; + } + + protected: + // interface for the derived class + + state_machine(state_t const& initial_state) + : m_state(initial_state) + { + } + + state_machine() + : m_state(typename Derived::initial_state()) + { + } + + virtual ~state_machine() + { + } + + void post_event(std::auto_ptr evt) + { + m_events_queue.push(base_event_ptr_t(evt.release())); + } + + template< + long State + , void (Derived::* invariant_func)() const = 0 + > + struct state + : fsm::aux::state + { + }; + + template< + typename From + , typename Event + , typename To + , bool (Derived::* transition_func)(Event const&) + > + struct transition + : aux::transition< Derived,From,Event,To,transition_func > + { + }; + + private: + + void do_transition(base_event_t const& evt) + { + typedef typename Derived::transition_table STT_; + typedef typename aux::STT_impl_gen< STT_ >::type STT_impl_; + + m_state = STT_impl_::do_transition( + static_cast(*this) + , m_state + , evt + ); + } + + state_t m_state; + std::queue< base_event_ptr_t > m_events_queue; +}; + +} // namespace fsm + +#endif // BOOST_FSM_STATE_MACHINE_INCLUDED diff --git a/example/inherit_linearly.cpp b/example/inherit_linearly.cpp new file mode 100644 index 0000000..8215a19 --- /dev/null +++ b/example/inherit_linearly.cpp @@ -0,0 +1,65 @@ +//----------------------------------------------------------------------------- +// boost mpl/example/inherit_linearly.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#include "boost/mpl/inherit_linearly.hpp" +#include "boost/mpl/int_c.hpp" +#include "boost/mpl/list.hpp" + +#include + +namespace mpl = boost::mpl; +using namespace mpl::placeholder; + +template< typename Base, typename T > +struct tuple_part + : Base +{ + typedef tuple_part type; // note the typedef + typedef typename Base::index::next index; + + friend T& field(tuple_part& t, index) { return t.field_; } + T field_; +}; + +struct empty_tuple +{ + typedef mpl::int_c<-1> index; +}; + + +typedef mpl::inherit_linearly< + mpl::list + , tuple_part<_,_> + , empty_tuple + >::type my_tuple; + + +int main() +{ + my_tuple t; + + field(t, mpl::int_c<0>()) = -1; + field(t, mpl::int_c<1>()) = "text"; + field(t, mpl::int_c<2>()) = false; + + std::cout + << field(t, mpl::int_c<0>()) << '\n' + << field(t, mpl::int_c<1>()) << '\n' + << field(t, mpl::int_c<2>()) << '\n' + ; + + return 0; +} diff --git a/example/inherit_multiply.cpp b/example/inherit_multiply.cpp new file mode 100644 index 0000000..553b8d8 --- /dev/null +++ b/example/inherit_multiply.cpp @@ -0,0 +1,61 @@ +//----------------------------------------------------------------------------- +// boost mpl/example/inherit_multiply.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2002 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#include "boost/mpl/inherit.hpp" +#include "boost/mpl/inherit_linearly.hpp" +#include "boost/mpl/list.hpp" + +#include + +namespace mpl = boost::mpl; +using namespace mpl::placeholder; + +template< typename T > +struct tuple_field +{ + typedef tuple_field type; // note the typedef + T field_; +}; + +template< typename T > +inline +T& field(tuple_field& t) +{ + return t.field_; +} + +typedef mpl::inherit_linearly< + mpl::list + , mpl::inherit< _1, tuple_field<_2> > + >::type my_tuple; + + +int main() +{ + my_tuple t; + + field(t) = -1; + field(t) = "text"; + field(t) = false; + + std::cout + << field(t) << '\n' + << field(t) << '\n' + << field(t) << '\n' + ; + + return 0; +} diff --git a/example/integer.cpp b/example/integer.cpp new file mode 100644 index 0000000..22845eb --- /dev/null +++ b/example/integer.cpp @@ -0,0 +1,68 @@ +//----------------------------------------------------------------------------- +// boost mpl/example/integer.cpp source file +// See http://www.boost.org for updates, documentation, and revision history. +//----------------------------------------------------------------------------- +// +// Copyright (c) 2001-02 +// Aleksey Gurtovoy +// +// Permission to use, copy, modify, distribute and sell this software +// and its documentation for any purpose is hereby granted without fee, +// provided that the above copyright notice appears in all copies and +// that both the copyright notice and this permission notice appear in +// supporting documentation. No representations are made about the +// suitability of this software for any purpose. It is provided "as is" +// without express or implied warranty. + +#include "boost/mpl/arithmetic/multiplies.hpp" +#include "boost/mpl/list.hpp" +#include "boost/mpl/lower_bound.hpp" +#include "boost/mpl/transform_view.hpp" +#include "boost/mpl/sizeof.hpp" +#include "boost/mpl/int_c.hpp" +#include "boost/mpl/identity.hpp" +#include "boost/mpl/base.hpp" +#include "boost/mpl/apply_if.hpp" +#include "boost/mpl/apply.hpp" +#include "boost/mpl/begin_end.hpp" +#include "boost/mpl/assert_is_same.hpp" + +namespace mpl = boost::mpl; +using namespace mpl::placeholder; + +template< int bit_size > +class big_int +{ + // ... +}; + +template< int bit_size > +struct integer +{ + typedef mpl::list builtins_; + typedef typename mpl::base< typename mpl::lower_bound< + mpl::transform_view< builtins_ + , mpl::multiplies< mpl::sizeof_<_1>, mpl::int_c<8> > + > + , mpl::int_c + >::type >::type iter_; + + typedef typename mpl::end::type last_; + typedef typename mpl::apply_if< + boost::is_same + , mpl::identity< big_int > + , mpl::apply0 + >::type type; +}; + +typedef integer<1>::type int1; +typedef integer<5>::type int5; +typedef integer<15>::type int15; +typedef integer<32>::type int32; +typedef integer<100>::type int100; + +BOOST_MPL_ASSERT_IS_SAME(int1, char); +BOOST_MPL_ASSERT_IS_SAME(int5, char); +BOOST_MPL_ASSERT_IS_SAME(int15, short); +BOOST_MPL_ASSERT_IS_SAME(int32, int); +BOOST_MPL_ASSERT_IS_SAME(int100, big_int<100>);