📄 state_machine.hpp
字号:
#ifndef BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
#define BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2006 Andreas Huber Doenni
// Distributed under the Boost Software License, Version 1.0. (See accompany-
// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
//////////////////////////////////////////////////////////////////////////////
#include <boost/statechart/event.hpp>
#include <boost/statechart/null_exception_translator.hpp>
#include <boost/statechart/result.hpp>
#include <boost/statechart/detail/rtti_policy.hpp>
#include <boost/statechart/detail/state_base.hpp>
#include <boost/statechart/detail/leaf_state.hpp>
#include <boost/statechart/detail/node_state.hpp>
#include <boost/statechart/detail/constructor.hpp>
#include <boost/statechart/detail/avoid_unused_warning.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/clear.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/minus.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/type_traits/is_pointer.hpp>
#include <boost/type_traits/remove_reference.hpp>
#include <boost/noncopyable.hpp>
#include <boost/assert.hpp>
#include <boost/static_assert.hpp>
#include <boost/cast.hpp> // boost::polymorphic_downcast
// BOOST_NO_EXCEPTIONS, BOOST_MSVC, BOOST_MSVC_STD_ITERATOR
#include <boost/config.hpp>
#include <boost/detail/allocator_utilities.hpp>
#ifdef BOOST_MSVC
# pragma warning( push )
# pragma warning( disable: 4702 ) // unreachable code (in release mode only)
#endif
#include <map>
#ifdef BOOST_MSVC
# pragma warning( pop )
#endif
#include <memory> // std::allocator
#include <typeinfo> // std::bad_cast
#include <functional> // std::less
#include <iterator>
#ifdef BOOST_MSVC
// We permanently turn off the following level 4 warnings because users will
// have to do so themselves anyway if we turn them back on
# pragma warning( disable: 4511 ) // copy constructor could not be generated
# pragma warning( disable: 4512 ) // assignment op could not be generated
#endif
namespace boost
{
namespace statechart
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
template< class StateBaseType, class EventBaseType, class IdType >
class send_function
{
public:
//////////////////////////////////////////////////////////////////////////
send_function(
StateBaseType & toState,
const EventBaseType & evt,
IdType eventType
) :
toState_( toState ), evt_( evt ), eventType_( eventType )
{
}
result operator()()
{
return detail::result_utility::make_result(
toState_.react_impl( evt_, eventType_ ) );
}
private:
//////////////////////////////////////////////////////////////////////////
StateBaseType & toState_;
const EventBaseType & evt_;
IdType eventType_;
};
//////////////////////////////////////////////////////////////////////////////
struct state_cast_impl_pointer_target
{
public:
//////////////////////////////////////////////////////////////////////////
template< class StateBaseType >
static const StateBaseType * deref_if_necessary(
const StateBaseType * pState )
{
return pState;
}
template< class Target, class IdType >
static IdType type_id()
{
Target p = 0;
return type_id_impl< IdType >( p );
}
static bool found( const void * pFound )
{
return pFound != 0;
}
template< class Target >
static Target not_found()
{
return 0;
}
private:
//////////////////////////////////////////////////////////////////////////
template< class IdType, class Type >
static IdType type_id_impl( const Type * )
{
return Type::static_type();
}
};
struct state_cast_impl_reference_target
{
template< class StateBaseType >
static const StateBaseType & deref_if_necessary(
const StateBaseType * pState )
{
return *pState;
}
template< class Target, class IdType >
static IdType type_id()
{
return remove_reference< Target >::type::static_type();
}
template< class Dummy >
static bool found( const Dummy & )
{
return true;
}
template< class Target >
static Target not_found()
{
throw std::bad_cast();
}
};
template< class Target >
struct state_cast_impl : public mpl::if_<
is_pointer< Target >,
state_cast_impl_pointer_target,
state_cast_impl_reference_target
>::type {};
//////////////////////////////////////////////////////////////////////////////
template< class RttiPolicy >
class history_key
{
public:
//////////////////////////////////////////////////////////////////////////
template< class HistorizedState >
static history_key make_history_key()
{
return history_key(
HistorizedState::context_type::static_type(),
HistorizedState::orthogonal_position::value );
}
typename RttiPolicy::id_type history_context_type() const
{
return historyContextType_;
}
friend bool operator<(
const history_key & left, const history_key & right )
{
return
std::less< typename RttiPolicy::id_type >()(
left.historyContextType_, right.historyContextType_ ) ||
( ( left.historyContextType_ == right.historyContextType_ ) &&
( left.historizedOrthogonalRegion_ <
right.historizedOrthogonalRegion_ ) );
}
private:
//////////////////////////////////////////////////////////////////////////
history_key(
typename RttiPolicy::id_type historyContextType,
orthogonal_position_type historizedOrthogonalRegion
) :
historyContextType_( historyContextType ),
historizedOrthogonalRegion_( historizedOrthogonalRegion )
{
}
const typename RttiPolicy::id_type historyContextType_;
const orthogonal_position_type historizedOrthogonalRegion_;
};
} // namespace detail
//////////////////////////////////////////////////////////////////////////////
template< class MostDerived,
class InitialState,
class Allocator = std::allocator< void >,
class ExceptionTranslator = null_exception_translator >
class state_machine : noncopyable
{
public:
//////////////////////////////////////////////////////////////////////////
typedef Allocator allocator_type;
typedef detail::rtti_policy rtti_policy_type;
typedef event_base event_base_type;
typedef intrusive_ptr< const event_base_type > event_base_ptr_type;
void initiate()
{
terminate();
{
terminator guard( *this );
detail::result_utility::get_result( translator_(
initial_construct_function( *this ),
exception_event_handler( *this ) ) );
guard.dismiss();
}
process_queued_events();
}
void terminate()
{
terminator guard( *this );
detail::result_utility::get_result( translator_(
terminate_function( *this ),
exception_event_handler( *this ) ) );
guard.dismiss();
}
bool terminated() const
{
return pOutermostState_ == 0;
}
void process_event( const event_base_type & evt )
{
send_event( evt );
process_queued_events();
}
template< class Target >
Target state_cast() const
{
typedef detail::state_cast_impl< Target > impl;
for ( typename state_list_type::const_iterator pCurrentLeafState =
currentStates_.begin();
pCurrentLeafState != currentStatesEnd_;
++pCurrentLeafState )
{
const state_base_type * pCurrentState(
get_pointer( *pCurrentLeafState ) );
while ( pCurrentState != 0 )
{
// The unnecessary try/catch overhead for pointer targets is
// typically small compared to the cycles dynamic_cast needs
#ifndef BOOST_NO_EXCEPTIONS
try
#endif
{
Target result = dynamic_cast< Target >(
impl::deref_if_necessary( pCurrentState ) );
if ( impl::found( result ) )
{
return result;
}
}
#ifndef BOOST_NO_EXCEPTIONS
// Intentionally swallow std::bad_cast exceptions. We'll throw one
// ourselves when we fail to find a state that can be cast to Target
catch ( const std::bad_cast & ) {}
#endif
pCurrentState = pCurrentState->outer_state_ptr();
}
}
return impl::template not_found< Target >();
}
template< class Target >
Target state_downcast() const
{
typedef detail::state_cast_impl< Target > impl;
typename rtti_policy_type::id_type targetType =
impl::template type_id< Target, rtti_policy_type::id_type >();
for ( typename state_list_type::const_iterator pCurrentLeafState =
currentStates_.begin();
pCurrentLeafState != currentStatesEnd_;
++pCurrentLeafState )
{
const state_base_type * pCurrentState(
get_pointer( *pCurrentLeafState ) );
while ( pCurrentState != 0 )
{
if ( pCurrentState->dynamic_type() == targetType )
{
return static_cast< Target >(
impl::deref_if_necessary( pCurrentState ) );
}
pCurrentState = pCurrentState->outer_state_ptr();
}
}
return impl::template not_found< Target >();
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -