boost/msm/front/functor_row.hpp
// Copyright 2008 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)
#ifndef BOOST_MSM_FRONT_FUNCTOR_ROW_H
#define BOOST_MSM_FRONT_FUNCTOR_ROW_H
#include <boost/mpl/set.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/mpl/has_xxx.hpp>
#include <boost/mpl/count_if.hpp>
#include <boost/fusion/container/set.hpp>
#include <boost/fusion/container/vector.hpp>
#include <boost/typeof/typeof.hpp>
#include <boost/msm/back/common_types.hpp>
#include <boost/msm/row_tags.hpp>
#include <boost/msm/common.hpp>
#include <boost/msm/front/completion_event.hpp>
#include BOOST_TYPEOF_INCREMENT_REGISTRATION_GROUP()
BOOST_MPL_HAS_XXX_TRAIT_DEF(deferring_action)
BOOST_MPL_HAS_XXX_TRAIT_DEF(some_deferring_actions)
namespace boost { namespace msm { namespace front
{
template <class Func,class Enable=void>
struct get_functor_return_value
{
static const ::boost::msm::back::HandledEnum value = ::boost::msm::back::HANDLED_TRUE;
};
template <class Func>
struct get_functor_return_value<Func,
typename ::boost::enable_if<
typename has_deferring_action<Func>::type
>::type
>
{
static const ::boost::msm::back::HandledEnum value = ::boost::msm::back::HANDLED_DEFERRED;
};
// for sequences
template <class Func>
struct get_functor_return_value<Func,
typename ::boost::enable_if<
typename has_some_deferring_actions<Func>::type
>::type
>
{
static const ::boost::msm::back::HandledEnum value =
(Func::some_deferring_actions::value ? ::boost::msm::back::HANDLED_DEFERRED : ::boost::msm::back::HANDLED_TRUE );
};
template <class SOURCE,class EVENT,class TARGET,class ACTION=none,class GUARD=none>
struct Row
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef TARGET Target;
typedef ACTION Action;
typedef GUARD Guard;
// action plus guard
typedef row_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
Action()(evt,fsm,src,tgt);
return get_functor_return_value<Action>::value;
}
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static bool guard_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt,AllStates&)
{
// create functor, call it
return Guard()(evt,fsm,src,tgt);
}
};
template<class SOURCE,class EVENT,class TARGET>
struct Row<SOURCE,EVENT,TARGET,none,none>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef TARGET Target;
typedef none Action;
typedef none Guard;
// no action, no guard
typedef _row_tag row_type_tag;
};
template<class SOURCE,class EVENT,class TARGET,class ACTION>
struct Row<SOURCE,EVENT,TARGET,ACTION,none>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef TARGET Target;
typedef ACTION Action;
typedef none Guard;
// no guard
typedef a_row_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
Action()(evt,fsm,src,tgt);
return get_functor_return_value<Action>::value;
}
};
template<class SOURCE,class EVENT,class TARGET,class GUARD>
struct Row<SOURCE,EVENT,TARGET,none,GUARD>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef TARGET Target;
typedef none Action;
typedef GUARD Guard;
// no action
typedef g_row_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static bool guard_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
return Guard()(evt,fsm,src,tgt);
}
};
// internal transitions
template<class SOURCE,class EVENT,class ACTION>
struct Row<SOURCE,EVENT,none,ACTION,none>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef Source Target;
typedef ACTION Action;
typedef none Guard;
// no guard
typedef a_irow_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
Action()(evt,fsm,src,tgt);
return get_functor_return_value<Action>::value;
}
};
template<class SOURCE,class EVENT,class GUARD>
struct Row<SOURCE,EVENT,none,none,GUARD>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef Source Target;
typedef none Action;
typedef GUARD Guard;
// no action
typedef g_irow_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static bool guard_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
return Guard()(evt,fsm,src,tgt);
}
};
template<class SOURCE,class EVENT,class ACTION,class GUARD>
struct Row<SOURCE,EVENT,none,ACTION,GUARD>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef Source Target;
typedef ACTION Action;
typedef GUARD Guard;
// action + guard
typedef irow_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
Action()(evt,fsm,src,tgt);
return get_functor_return_value<Action>::value;
}
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static bool guard_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
return Guard()(evt,fsm,src,tgt);
}
};
template<class SOURCE,class EVENT>
struct Row<SOURCE,EVENT,none,none,none>
{
typedef SOURCE Source;
typedef EVENT Evt;
typedef Source Target;
typedef none Action;
typedef none Guard;
// no action, no guard
typedef _irow_tag row_type_tag;
};
template<class TGT>
struct get_row_target
{
typedef typename TGT::Target type;
};
template <class EVENT,class ACTION=none,class GUARD=none>
struct Internal
{
typedef EVENT Evt;
typedef ACTION Action;
typedef GUARD Guard;
// action plus guard
typedef sm_i_row_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
Action()(evt,fsm,src,tgt);
return get_functor_return_value<Action>::value;
}
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static bool guard_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
return Guard()(evt,fsm,src,tgt);
}
};
template<class EVENT,class ACTION>
struct Internal<EVENT,ACTION,none>
{
typedef EVENT Evt;
typedef ACTION Action;
typedef none Guard;
// no guard
typedef sm_a_i_row_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static ::boost::msm::back::HandledEnum action_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
Action()(evt,fsm,src,tgt);
return get_functor_return_value<Action>::value;
}
};
template<class EVENT,class GUARD>
struct Internal<EVENT,none,GUARD>
{
typedef EVENT Evt;
typedef none Action;
typedef GUARD Guard;
// no action
typedef sm_g_i_row_tag row_type_tag;
template <class EVT,class FSM,class SourceState,class TargetState,class AllStates>
static bool guard_call(FSM& fsm,EVT& evt,SourceState& src,TargetState& tgt, AllStates&)
{
// create functor, call it
return Guard()(evt,fsm,src,tgt);
}
};
template<class EVENT>
struct Internal<EVENT,none,none>
{
typedef EVENT Evt;
typedef none Action;
typedef none Guard;
// no action, no guard
typedef sm__i_row_tag row_type_tag;
};
struct event_tag{};
struct action_tag{};
struct state_action_tag{};
struct flag_tag{};
struct config_tag{};
struct not_euml_tag{};
template <class Sequence>
struct ActionSequence_
{
typedef Sequence sequence;
// if one functor of the sequence defers events, the complete sequence does
typedef ::boost::mpl::bool_<
::boost::mpl::count_if<sequence,
has_deferring_action< ::boost::mpl::placeholders::_1 >
>::value != 0> some_deferring_actions;
template <class Event,class FSM,class STATE >
struct state_action_result
{
typedef void type;
};
template <class EVT,class FSM,class STATE>
struct Call
{
Call(EVT& evt,FSM& fsm,STATE& state):
evt_(evt),fsm_(fsm),state_(state){}
template <class FCT>
void operator()(::boost::msm::wrap<FCT> const& )
{
FCT()(evt_,fsm_,state_);
}
private:
EVT& evt_;
FSM& fsm_;
STATE& state_;
};
template <class EVT,class FSM,class SourceState,class TargetState>
struct transition_action_result
{
typedef void type;
};
template <class EVT,class FSM,class SourceState,class TargetState>
struct Call2
{
Call2(EVT& evt,FSM& fsm,SourceState& src,TargetState& tgt):
evt_(evt),fsm_(fsm),src_(src),tgt_(tgt){}
template <class FCT>
void operator()(::boost::msm::wrap<FCT> const& )
{
FCT()(evt_,fsm_,src_,tgt_);
}
private:
EVT& evt_;
FSM& fsm_;
SourceState& src_;
TargetState& tgt_;
};
typedef ::boost::fusion::set<state_action_tag,action_tag> tag_type;
template <class EVT,class FSM,class STATE>
void operator()(EVT& evt,FSM& fsm,STATE& state)
{
mpl::for_each<Sequence,boost::msm::wrap< ::boost::mpl::placeholders::_1> >
(Call<EVT,FSM,STATE>(evt,fsm,state));
}
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT& evt,FSM& fsm,SourceState& src,TargetState& tgt)
{
mpl::for_each<Sequence,boost::msm::wrap< ::boost::mpl::placeholders::_1> >
(Call2<EVT,FSM,SourceState,TargetState>(evt,fsm,src,tgt));
}
};
// functor pre-defined for basic functionality
struct Defer
{
// mark as deferring to avoid stack overflows in certain conditions
typedef int deferring_action;
template <class EVT,class FSM,class SourceState,class TargetState>
void operator()(EVT& evt,FSM& fsm,SourceState& ,TargetState& ) const
{
fsm.defer_event(evt);
}
};
}}}
#endif //BOOST_MSM_FRONT_FUNCTOR_ROW_H