Added boost header

This commit is contained in:
Christophe Riccio
2012-01-08 01:26:07 +00:00
parent 9c3faaca40
commit c7d752cdf8
8946 changed files with 1732316 additions and 0 deletions

View File

@@ -0,0 +1,89 @@
#ifndef BOOST_STATECHART_ASYNCHRONOUS_STATE_MACHINE_HPP_INCLUDED
#define BOOST_STATECHART_ASYNCHRONOUS_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/state_machine.hpp>
#include <boost/statechart/fifo_scheduler.hpp>
#include <boost/statechart/null_exception_translator.hpp>
#include <boost/statechart/event_processor.hpp>
#include <memory> // std::allocator
namespace boost
{
namespace statechart
{
class event_base;
//////////////////////////////////////////////////////////////////////////////
template< class MostDerived,
class InitialState,
class Scheduler = fifo_scheduler<>,
class Allocator = std::allocator< void >,
class ExceptionTranslator = null_exception_translator >
class asynchronous_state_machine : public state_machine<
MostDerived, InitialState, Allocator, ExceptionTranslator >,
public event_processor< Scheduler >
{
typedef state_machine< MostDerived,
InitialState, Allocator, ExceptionTranslator > machine_base;
typedef event_processor< Scheduler > processor_base;
protected:
//////////////////////////////////////////////////////////////////////////
typedef asynchronous_state_machine my_base;
asynchronous_state_machine( typename processor_base::my_context ctx ) :
processor_base( ctx )
{
}
virtual ~asynchronous_state_machine() {}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
void terminate()
{
processor_base::terminate();
}
private:
//////////////////////////////////////////////////////////////////////////
virtual void initiate_impl()
{
machine_base::initiate();
}
virtual void process_event_impl( const event_base & evt )
{
machine_base::process_event( evt );
}
virtual void terminate_impl()
{
machine_base::terminate();
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,74 @@
#ifndef BOOST_STATECHART_CUSTOM_REACTION_HPP_INCLUDED
#define BOOST_STATECHART_CUSTOM_REACTION_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/result.hpp>
#include <boost/cast.hpp> // boost::polymorphic_downcast
namespace boost
{
namespace statechart
{
class event_base;
//////////////////////////////////////////////////////////////////////////////
template< class Event >
class custom_reaction
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase & evt, const IdType & eventType )
{
if ( eventType == Event::static_type() )
{
return detail::result_utility::get_result(
stt.react( *polymorphic_downcast< const Event * >( &evt ) ) );
}
else
{
return detail::no_reaction;
}
}
};
template<>
class custom_reaction< event_base >
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase & evt, const IdType & )
{
return detail::result_utility::get_result( stt.react( evt ) );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,63 @@
#ifndef BOOST_STATECHART_DEEP_HISTORY_HPP_INCLUDED
#define BOOST_STATECHART_DEEP_HISTORY_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/mpl/bool.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
template< class DefaultState >
class deep_history
{
public:
//////////////////////////////////////////////////////////////////////////
// If you receive a
// "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
// compiler error here then you forgot to pass either
// statechart::has_deep_history or statechart::has_full_history as the
// last parameter of DefaultState's context.
BOOST_STATIC_ASSERT( DefaultState::context_type::deep_history::value );
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
typedef typename DefaultState::outermost_context_base_type
outermost_context_base_type;
typedef typename DefaultState::context_type context_type;
typedef typename DefaultState::context_ptr_type context_ptr_type;
typedef typename DefaultState::context_type_list context_type_list;
typedef typename DefaultState::orthogonal_position orthogonal_position;
static void deep_construct(
const context_ptr_type & pContext,
outermost_context_base_type & outermostContextBase )
{
outermostContextBase.template construct_with_deep_history<
DefaultState >( pContext );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,71 @@
#ifndef BOOST_STATECHART_DEFERRAL_HPP_INCLUDED
#define BOOST_STATECHART_DEFERRAL_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/result.hpp>
namespace boost
{
namespace statechart
{
class event_base;
//////////////////////////////////////////////////////////////////////////////
template< class Event >
class deferral
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase &, const IdType & eventType )
{
if ( eventType == Event::static_type() )
{
return detail::result_utility::get_result( stt.defer_event() );
}
else
{
return detail::no_reaction;
}
}
};
template<>
class deferral< event_base >
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase &, const IdType & )
{
return detail::result_utility::get_result( stt.defer_event() );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,31 @@
#ifndef BOOST_STATECHART_DETAIL_AVOID_UNUSED_WARNING_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_AVOID_UNUSED_WARNING_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)
//////////////////////////////////////////////////////////////////////////////
namespace boost
{
namespace statechart
{
namespace detail
{
template< typename T >
inline void avoid_unused_warning( const T & ) {}
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,139 @@
#ifndef BOOST_STATECHART_DETAIL_CONSTRUCTOR_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_CONSTRUCTOR_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/mpl/eval_if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/advance.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/erase.hpp>
#include <boost/mpl/reverse.hpp>
#include <boost/mpl/long.hpp>
namespace boost
{
namespace statechart
{
namespace detail
{
template< class ContextList, class OutermostContextBase >
struct constructor;
//////////////////////////////////////////////////////////////////////////////
template< class ContextList, class OutermostContextBase >
struct outer_constructor
{
typedef typename mpl::front< ContextList >::type to_construct;
typedef typename to_construct::context_ptr_type context_ptr_type;
typedef typename to_construct::inner_context_ptr_type
inner_context_ptr_type;
typedef typename to_construct::inner_initial_list inner_initial_list;
typedef typename mpl::pop_front< ContextList >::type inner_context_list;
typedef typename mpl::front< inner_context_list >::type::orthogonal_position
inner_orthogonal_position;
typedef typename mpl::advance<
typename mpl::begin< inner_initial_list >::type,
inner_orthogonal_position >::type to_construct_iter;
typedef typename mpl::erase<
inner_initial_list,
to_construct_iter,
typename mpl::end< inner_initial_list >::type
>::type first_inner_initial_list;
typedef typename mpl::erase<
inner_initial_list,
typename mpl::begin< inner_initial_list >::type,
typename mpl::next< to_construct_iter >::type
>::type last_inner_initial_list;
static void construct(
const context_ptr_type & pContext,
OutermostContextBase & outermostContextBase )
{
const inner_context_ptr_type pInnerContext =
to_construct::shallow_construct( pContext, outermostContextBase );
to_construct::template deep_construct_inner<
first_inner_initial_list >( pInnerContext, outermostContextBase );
constructor< inner_context_list, OutermostContextBase >::construct(
pInnerContext, outermostContextBase );
to_construct::template deep_construct_inner<
last_inner_initial_list >( pInnerContext, outermostContextBase );
}
};
//////////////////////////////////////////////////////////////////////////////
template< class ContextList, class OutermostContextBase >
struct inner_constructor
{
typedef typename mpl::front< ContextList >::type to_construct;
typedef typename to_construct::context_ptr_type context_ptr_type;
static void construct(
const context_ptr_type & pContext,
OutermostContextBase & outermostContextBase )
{
to_construct::deep_construct( pContext, outermostContextBase );
}
};
//////////////////////////////////////////////////////////////////////////////
template< class ContextList, class OutermostContextBase >
struct constructor_impl : public mpl::eval_if<
mpl::equal_to< mpl::size< ContextList >, mpl::long_< 1 > >,
mpl::identity< inner_constructor< ContextList, OutermostContextBase > >,
mpl::identity< outer_constructor< ContextList, OutermostContextBase > > >
{
};
//////////////////////////////////////////////////////////////////////////////
template< class ContextList, class OutermostContextBase >
struct constructor :
constructor_impl< ContextList, OutermostContextBase >::type {};
//////////////////////////////////////////////////////////////////////////////
template< class CommonContext, class DestinationState >
struct make_context_list
{
typedef typename mpl::reverse< typename mpl::push_front<
typename mpl::erase<
typename DestinationState::context_type_list,
typename mpl::find<
typename DestinationState::context_type_list,
CommonContext
>::type,
typename mpl::end<
typename DestinationState::context_type_list
>::type
>::type,
DestinationState
>::type >::type type;
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,92 @@
#ifndef BOOST_STATECHART_DETAIL_COUNTED_BASE_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_COUNTED_BASE_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/detail/atomic_count.hpp>
#include <boost/config.hpp> // BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
namespace boost
{
namespace statechart
{
namespace detail
{
template< bool NeedsLocking >
struct count_base
{
count_base() : count_( 0 ) {}
mutable boost::detail::atomic_count count_;
};
template<>
struct count_base< false >
{
count_base() : count_( 0 ) {}
mutable long count_;
};
//////////////////////////////////////////////////////////////////////////////
template< bool NeedsLocking = true >
class counted_base : private count_base< NeedsLocking >
{
typedef count_base< NeedsLocking > base_type;
public:
//////////////////////////////////////////////////////////////////////////
bool ref_counted() const
{
return base_type::count_ != 0;
}
long ref_count() const
{
return base_type::count_;
}
protected:
//////////////////////////////////////////////////////////////////////////
counted_base() {}
~counted_base() {}
// do nothing copy implementation is intentional (the number of
// referencing pointers of the source and the destination is not changed
// through the copy operation)
counted_base( const counted_base & ) : base_type() {}
counted_base & operator=( const counted_base & ) { return *this; }
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
void add_ref() const
{
++base_type::count_;
}
bool release() const
{
BOOST_ASSERT( base_type::count_ > 0 );
return --base_type::count_ == 0;
}
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,84 @@
#ifndef BOOST_STATECHART_DETAIL_LEAF_STATE_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_LEAF_STATE_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/detail/state_base.hpp>
namespace boost
{
namespace statechart
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
template< class Allocator, class RttiPolicy >
class leaf_state : public state_base< Allocator, RttiPolicy >
{
typedef state_base< Allocator, RttiPolicy > base_type;
protected:
//////////////////////////////////////////////////////////////////////////
leaf_state( typename RttiPolicy::id_provider_type idProvider ) :
base_type( idProvider )
{
}
~leaf_state() {}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
void set_list_position(
typename base_type::state_list_type::iterator listPosition )
{
listPosition_ = listPosition;
}
typedef typename base_type::leaf_state_ptr_type
direct_state_base_ptr_type;
virtual void remove_from_state_list(
typename base_type::state_list_type::iterator & statesEnd,
typename base_type::node_state_base_ptr_type & pOutermostUnstableState,
bool performFullExit )
{
--statesEnd;
swap( *listPosition_, *statesEnd );
( *listPosition_ )->set_list_position( listPosition_ );
direct_state_base_ptr_type & pState = *statesEnd;
// Because the list owns the leaf_state, this leads to the immediate
// termination of this state.
pState->exit_impl( pState, pOutermostUnstableState, performFullExit );
}
virtual void exit_impl(
direct_state_base_ptr_type & pSelf,
typename base_type::node_state_base_ptr_type & pOutermostUnstableState,
bool performFullExit ) = 0;
private:
//////////////////////////////////////////////////////////////////////////
typename base_type::state_list_type::iterator listPosition_;
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,72 @@
#ifndef BOOST_STATECHART_DETAIL_MEMORY_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_MEMORY_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2005-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/detail/avoid_unused_warning.hpp>
#include <boost/assert.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <cstddef> // std::size_t
namespace boost
{
namespace statechart
{
namespace detail
{
template< class MostDerived, class Allocator >
void * allocate( std::size_t size )
{
avoid_unused_warning( size );
// The assert below fails when memory is allocated for an event<>,
// simple_state<> or state<> subtype object, *and* the first template
// parameter passed to one of these templates is not equal to the most-
// derived object being constructed.
// The following examples apply to all these subtypes:
// // Example 1
// struct A {};
// struct B : sc::simple_state< A, /* ... */ >
// // Above, the first template parameter must be equal to the most-
// // derived type
//
// // Example 2
// struct A : sc::event< A >
// struct B : A { /* ... */ };
// void f() { delete new B(); }
// // Above the most-derived type being constructed is B, but A was passed
// // as the most-derived type to event<>.
BOOST_ASSERT( size == sizeof( MostDerived ) );
return typename boost::detail::allocator::rebind_to<
Allocator, MostDerived
>::type().allocate( 1, static_cast< MostDerived * >( 0 ) );
}
template< class MostDerived, class Allocator >
void deallocate( void * pObject )
{
return typename boost::detail::allocator::rebind_to<
Allocator, MostDerived
>::type().deallocate( static_cast< MostDerived * >( pObject ), 1 );
}
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,156 @@
#ifndef BOOST_STATECHART_DETAIL_NODE_STATE_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_NODE_STATE_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/detail/state_base.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/assert.hpp> // BOOST_ASSERT
#include <algorithm> // std::find_if
namespace boost
{
namespace statechart
{
namespace detail
{
template< class Allocator, class RttiPolicy >
class node_state_base : public state_base< Allocator, RttiPolicy >
{
typedef state_base< Allocator, RttiPolicy > base_type;
protected:
//////////////////////////////////////////////////////////////////////////
node_state_base( typename RttiPolicy::id_provider_type idProvider ) :
base_type( idProvider )
{
}
~node_state_base() {}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
typedef base_type state_base_type;
typedef intrusive_ptr< node_state_base > direct_state_base_ptr_type;
virtual void exit_impl(
direct_state_base_ptr_type & pSelf,
typename base_type::node_state_base_ptr_type & pOutermostUnstableState,
bool performFullExit ) = 0;
};
//////////////////////////////////////////////////////////////////////////////
template< class OrthogonalRegionCount, class Allocator, class RttiPolicy >
class node_state : public node_state_base< Allocator, RttiPolicy >
{
typedef node_state_base< Allocator, RttiPolicy > base_type;
protected:
//////////////////////////////////////////////////////////////////////////
node_state( typename RttiPolicy::id_provider_type idProvider ) :
base_type( idProvider )
{
for ( orthogonal_position_type pos = 0;
pos < OrthogonalRegionCount::value; ++pos )
{
pInnerStates[ pos ] = 0;
}
}
~node_state() {}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
typedef typename base_type::state_base_type state_base_type;
void add_inner_state( orthogonal_position_type position,
state_base_type * pInnerState )
{
BOOST_ASSERT( ( position < OrthogonalRegionCount::value ) &&
( pInnerStates[ position ] == 0 ) );
pInnerStates[ position ] = pInnerState;
}
void remove_inner_state( orthogonal_position_type position )
{
BOOST_ASSERT( position < OrthogonalRegionCount::value );
pInnerStates[ position ] = 0;
}
virtual void remove_from_state_list(
typename state_base_type::state_list_type::iterator & statesEnd,
typename state_base_type::node_state_base_ptr_type &
pOutermostUnstableState,
bool performFullExit )
{
state_base_type ** const pPastEnd =
&pInnerStates[ OrthogonalRegionCount::value ];
// We must not iterate past the last inner state because *this* state
// will no longer exist when the last inner state has been removed
state_base_type ** const pFirstNonNull = std::find_if(
&pInnerStates[ 0 ], pPastEnd, &node_state::is_not_null );
if ( pFirstNonNull == pPastEnd )
{
// The state does not have inner states but is still alive, this must
// be the outermost unstable state then.
BOOST_ASSERT( get_pointer( pOutermostUnstableState ) == this );
typename state_base_type::node_state_base_ptr_type pSelf =
pOutermostUnstableState;
pSelf->exit_impl( pSelf, pOutermostUnstableState, performFullExit );
}
else
{
// Destroy inner states in the reverse order of construction
for ( state_base_type ** pState = pPastEnd; pState != pFirstNonNull; )
{
--pState;
// An inner orthogonal state might have been terminated long before,
// that's why we have to check for 0 pointers
if ( *pState != 0 )
{
( *pState )->remove_from_state_list(
statesEnd, pOutermostUnstableState, performFullExit );
}
}
}
}
typedef typename base_type::direct_state_base_ptr_type
direct_state_base_ptr_type;
private:
//////////////////////////////////////////////////////////////////////////
static bool is_not_null( const state_base_type * pInner )
{
return pInner != 0;
}
state_base_type * pInnerStates[ OrthogonalRegionCount::value ];
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,121 @@
#ifndef BOOST_STATECHART_REACTION_DISPATCHER_HPP_INCLUDED
#define BOOST_STATECHART_REACTION_DISPATCHER_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2008 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/result.hpp>
#include <boost/mpl/if.hpp>
#include <boost/cast.hpp> // boost::polymorphic_downcast
#include <boost/type_traits/is_same.hpp>
namespace boost
{
namespace statechart
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
template< class Event >
struct no_context
{
void no_function( const Event & );
};
//////////////////////////////////////////////////////////////////////////////
template<
class Reactions, class State, class EventBase, class Event,
class ActionContext, class IdType >
class reaction_dispatcher
{
private:
struct without_action
{
static result react( State & stt, const EventBase & )
{
return Reactions::react_without_action( stt );
}
};
struct base_with_action
{
static result react( State & stt, const EventBase & evt )
{
return Reactions::react_with_action( stt, evt );
}
};
struct base
{
static result react(
State & stt, const EventBase & evt, const IdType & )
{
typedef typename mpl::if_<
is_same< ActionContext, detail::no_context< Event > >,
without_action, base_with_action
>::type reaction;
return reaction::react( stt, evt );
}
};
struct derived_with_action
{
static result react( State & stt, const EventBase & evt )
{
return Reactions::react_with_action(
stt, *polymorphic_downcast< const Event * >( &evt ) );
}
};
struct derived
{
static result react(
State & stt, const EventBase & evt, const IdType & eventType )
{
if ( eventType == Event::static_type() )
{
typedef typename mpl::if_<
is_same< ActionContext, detail::no_context< Event > >,
without_action, derived_with_action
>::type reaction;
return reaction::react( stt, evt );
}
else
{
return detail::result_utility::make_result( detail::no_reaction );
}
}
};
public:
static reaction_result react(
State & stt, const EventBase & evt, const IdType & eventType )
{
typedef typename mpl::if_<
is_same< Event, EventBase >, base, derived
>::type reaction;
return result_utility::get_result(
reaction::react( stt, evt, eventType ) );
}
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,208 @@
#ifndef BOOST_STATECHART_DETAIL_RTTI_POLICY_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_RTTI_POLICY_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2008 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/assert.hpp>
#include <boost/config.hpp> // BOOST_MSVC
#include <boost/detail/workaround.hpp>
#include <typeinfo> // std::type_info
namespace boost
{
namespace statechart
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
struct id_provider
{
const void * pCustomId_;
#if defined( BOOST_ENABLE_ASSERT_HANDLER ) || !defined( NDEBUG )
const std::type_info * pCustomIdType_;
#endif
};
template< class MostDerived >
struct id_holder
{
static id_provider idProvider_;
};
template< class MostDerived >
id_provider id_holder< MostDerived >::idProvider_;
//////////////////////////////////////////////////////////////////////////////
struct rtti_policy
{
#ifdef BOOST_STATECHART_USE_NATIVE_RTTI
class id_type
{
public:
////////////////////////////////////////////////////////////////////////
explicit id_type( const std::type_info & id ) : id_( id ) {}
bool operator==( id_type right ) const
{
return id_ == right.id_ != 0;
}
bool operator!=( id_type right ) const { return !( *this == right ); }
bool operator<( id_type right ) const
{
return id_.before( right.id_ ) != 0;
}
bool operator>( id_type right ) const { return right < *this; }
bool operator>=( id_type right ) const { return !( *this < right ); }
bool operator<=( id_type right ) const { return !( right < *this ); }
private:
////////////////////////////////////////////////////////////////////////
const std::type_info & id_;
};
typedef bool id_provider_type; // dummy
#else
typedef const void * id_type;
typedef const id_provider * id_provider_type;
#endif
////////////////////////////////////////////////////////////////////////////
template< class Base >
class rtti_base_type : public Base
{
public:
////////////////////////////////////////////////////////////////////////
typedef rtti_policy::id_type id_type;
id_type dynamic_type() const
{
#ifdef BOOST_STATECHART_USE_NATIVE_RTTI
return id_type( typeid( *this ) );
#else
return idProvider_;
#endif
}
#ifndef BOOST_STATECHART_USE_NATIVE_RTTI
template< typename CustomId >
const CustomId * custom_dynamic_type_ptr() const
{
BOOST_ASSERT(
( idProvider_->pCustomId_ == 0 ) ||
( *idProvider_->pCustomIdType_ == typeid( CustomId ) ) );
return static_cast< const CustomId * >( idProvider_->pCustomId_ );
}
#endif
protected:
#ifdef BOOST_STATECHART_USE_NATIVE_RTTI
rtti_base_type( id_provider_type ) {}
////////////////////////////////////////////////////////////////////////
#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT( 4 ) )
// We make the destructor virtual for GCC because with this compiler
// there is currently no way to disable the "has virtual functions but
// non-virtual destructor" warning on a class by class basis. Although
// it can be done on the compiler command line with
// -Wno-non-virtual-dtor, this is undesirable as this would also
// suppress legitimate warnings for types that are not states.
virtual ~rtti_base_type() {}
#else
~rtti_base_type() {}
#endif
private:
////////////////////////////////////////////////////////////////////////
// For typeid( *this ) to return a value that corresponds to the most-
// derived type, we need to have a vptr. Since this type does not
// contain any virtual functions we need to artificially declare one so.
virtual void dummy() {}
#else
rtti_base_type(
id_provider_type idProvider
) :
idProvider_( idProvider )
{
}
~rtti_base_type() {}
private:
////////////////////////////////////////////////////////////////////////
id_provider_type idProvider_;
#endif
};
////////////////////////////////////////////////////////////////////////////
template< class MostDerived, class Base >
class rtti_derived_type : public Base
{
public:
////////////////////////////////////////////////////////////////////////
static id_type static_type()
{
#ifdef BOOST_STATECHART_USE_NATIVE_RTTI
return id_type( typeid( const MostDerived ) );
#else
return &id_holder< MostDerived >::idProvider_;
#endif
}
#ifndef BOOST_STATECHART_USE_NATIVE_RTTI
template< class CustomId >
static const CustomId * custom_static_type_ptr()
{
BOOST_ASSERT(
( id_holder< MostDerived >::idProvider_.pCustomId_ == 0 ) ||
( *id_holder< MostDerived >::idProvider_.pCustomIdType_ ==
typeid( CustomId ) ) );
return static_cast< const CustomId * >(
id_holder< MostDerived >::idProvider_.pCustomId_ );
}
template< class CustomId >
static void custom_static_type_ptr( const CustomId * pCustomId )
{
#if defined( BOOST_ENABLE_ASSERT_HANDLER ) || !defined( NDEBUG )
id_holder< MostDerived >::idProvider_.pCustomIdType_ =
&typeid( CustomId );
#endif
id_holder< MostDerived >::idProvider_.pCustomId_ = pCustomId;
}
#endif
protected:
////////////////////////////////////////////////////////////////////////
~rtti_derived_type() {}
#ifdef BOOST_STATECHART_USE_NATIVE_RTTI
rtti_derived_type() : Base( false ) {}
#else
rtti_derived_type() : Base( &id_holder< MostDerived >::idProvider_ ) {}
#endif
};
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,191 @@
#ifndef BOOST_STATECHART_DETAIL_STATE_BASE_HPP_INCLUDED
#define BOOST_STATECHART_DETAIL_STATE_BASE_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2008 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/result.hpp>
#include <boost/statechart/event.hpp>
#include <boost/statechart/detail/counted_base.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/assert.hpp>
#include <boost/config.hpp> // BOOST_MSVC
#include <boost/detail/workaround.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 <list>
#ifdef BOOST_MSVC
# pragma warning( pop )
#endif
namespace boost
{
namespace statechart
{
namespace detail
{
template< class Allocator, class RttiPolicy >
class leaf_state;
template< class Allocator, class RttiPolicy >
class node_state_base;
typedef unsigned char orthogonal_position_type;
//////////////////////////////////////////////////////////////////////////////
template< class Allocator, class RttiPolicy >
class state_base :
#ifndef NDEBUG
noncopyable,
#endif
public RttiPolicy::template rtti_base_type<
// Derived class objects will be created, handled and destroyed by exactly
// one thread --> locking is not necessary
counted_base< false > >
{
typedef typename RttiPolicy::template rtti_base_type<
counted_base< false > > base_type;
public:
//////////////////////////////////////////////////////////////////////////
void exit() {}
virtual const state_base * outer_state_ptr() const = 0;
protected:
//////////////////////////////////////////////////////////////////////////
state_base( typename RttiPolicy::id_provider_type idProvider ) :
base_type( idProvider ),
deferredEvents_( false )
{
}
#if BOOST_WORKAROUND( __GNUC__, BOOST_TESTED_AT( 4 ) )
// We make the destructor virtual for GCC because with this compiler there
// is currently no way to disable the "has virtual functions but
// non-virtual destructor" warning on a class by class basis. Although it
// can be done on the compiler command line with -Wno-non-virtual-dtor,
// this is undesirable as this would also suppress legitimate warnings for
// types that are not states.
virtual ~state_base() {}
#else
// This destructor is not virtual for performance reasons. The library
// ensures that a state object is never deleted through a state_base
// pointer but only through a pointer to the most-derived type.
~state_base() {}
#endif
protected:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only protected because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
void defer_event()
{
deferredEvents_ = true;
}
bool deferred_events() const
{
return deferredEvents_;
}
template< class Context >
void set_context( orthogonal_position_type position, Context * pContext )
{
pContext->add_inner_state( position, this );
}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
virtual detail::reaction_result react_impl(
const event_base & evt,
typename RttiPolicy::id_type eventType ) = 0;
typedef intrusive_ptr< node_state_base< Allocator, RttiPolicy > >
node_state_base_ptr_type;
typedef intrusive_ptr< leaf_state< Allocator, RttiPolicy > >
leaf_state_ptr_type;
typedef std::list<
leaf_state_ptr_type,
typename boost::detail::allocator::rebind_to<
Allocator, leaf_state_ptr_type >::type
> state_list_type;
virtual void remove_from_state_list(
typename state_list_type::iterator & statesEnd,
node_state_base_ptr_type & pOutermostUnstableState,
bool performFullExit ) = 0;
private:
//////////////////////////////////////////////////////////////////////////
bool deferredEvents_;
};
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace detail
} // namespace statechart
#endif
template< class Allocator, class RttiPolicy >
inline void intrusive_ptr_add_ref(
const ::boost::statechart::detail::state_base< Allocator, RttiPolicy > * pBase )
{
pBase->add_ref();
}
template< class Allocator, class RttiPolicy >
inline void intrusive_ptr_release(
const ::boost::statechart::detail::state_base< Allocator, RttiPolicy > * pBase )
{
if ( pBase->release() )
{
// The state_base destructor is *not* virtual for performance reasons
// but intrusive_ptr< state_base > objects are nevertheless used to point
// to states. This assert ensures that such a pointer is never the last
// one referencing a state object.
BOOST_ASSERT( false );
}
}
#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace detail
} // namespace statechart
#endif
} // namespace boost
#endif

View File

@@ -0,0 +1,78 @@
#ifndef BOOST_STATECHART_EVENT_HPP_INCLUDED
#define BOOST_STATECHART_EVENT_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2007 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_base.hpp>
#include <boost/statechart/detail/rtti_policy.hpp>
#include <boost/statechart/detail/memory.hpp>
#include <boost/cast.hpp> // boost::polymorphic_downcast
#include <memory> // std::allocator
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
template< class MostDerived, class Allocator = std::allocator< void > >
class event : public detail::rtti_policy::rtti_derived_type<
MostDerived, event_base >
{
public:
//////////////////////////////////////////////////////////////////////////
// Compiler-generated copy constructor and copy assignment operator are
// fine
void * operator new( std::size_t size )
{
return detail::allocate< MostDerived, Allocator >( size );
}
void * operator new( std::size_t, void * p )
{
return p;
}
void operator delete( void * pEvent )
{
detail::deallocate< MostDerived, Allocator >( pEvent );
}
void operator delete( void * pEvent, void * p )
{
}
protected:
//////////////////////////////////////////////////////////////////////////
event() {}
virtual ~event() {}
private:
//////////////////////////////////////////////////////////////////////////
virtual intrusive_ptr< const event_base > clone() const
{
return intrusive_ptr< const event_base >( new MostDerived(
*polymorphic_downcast< const MostDerived * >( this ) ) );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,127 @@
#ifndef BOOST_STATECHART_EVENT_BASE_HPP_INCLUDED
#define BOOST_STATECHART_EVENT_BASE_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/detail/rtti_policy.hpp>
#include <boost/statechart/detail/counted_base.hpp>
#include <boost/assert.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/config.hpp>
namespace boost
{
namespace statechart
{
namespace detail
{
// This helper is necessary because there doesn't seem to be consensus among
// compilers on how a friend declaration for a function in another namespace
// has to look like.
class delete_helper
{
public:
template< class T >
static void delete_object( const T * pObject )
{
delete pObject;
}
};
} // namespace detail
//////////////////////////////////////////////////////////////////////////////
class event_base : public detail::rtti_policy::rtti_base_type<
detail::counted_base<> >
{
typedef detail::rtti_policy::rtti_base_type<
detail::counted_base<> > base_type;
public:
//////////////////////////////////////////////////////////////////////////
intrusive_ptr< const event_base > intrusive_from_this() const;
protected:
//////////////////////////////////////////////////////////////////////////
event_base( detail::rtti_policy::id_provider_type idProvider ) :
base_type( idProvider )
{
}
virtual ~event_base() {}
private:
//////////////////////////////////////////////////////////////////////////
virtual intrusive_ptr< const event_base > clone() const = 0;
friend class detail::delete_helper;
};
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace statechart
#endif
inline void intrusive_ptr_add_ref( const ::boost::statechart::event_base * pBase )
{
pBase->add_ref();
}
inline void intrusive_ptr_release( const ::boost::statechart::event_base * pBase )
{
if ( pBase->release() )
{
::boost::statechart::detail::delete_helper::delete_object( pBase );
}
}
#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace statechart
#endif
namespace statechart
{
// We're implementing this here so that GCC3.4.2 can find
// intrusive_ptr_add_ref, which is indirectly called from the intrusive_ptr
// ctor.
inline intrusive_ptr< const event_base > event_base::intrusive_from_this() const
{
if ( base_type::ref_counted() )
{
return intrusive_ptr< const event_base >( this );
}
else
{
return clone();
}
}
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,87 @@
#ifndef BOOST_STATECHART_EVENT_PROCESSOR_INCLUDED
#define BOOST_STATECHART_EVENT_PROCESSOR_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2008 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)
//////////////////////////////////////////////////////////////////////////////
namespace boost
{
namespace statechart
{
class event_base;
//////////////////////////////////////////////////////////////////////////////
template< class Scheduler >
class event_processor
{
public:
//////////////////////////////////////////////////////////////////////////
virtual ~event_processor() {}
Scheduler & my_scheduler() const
{
return myScheduler_;
}
typedef typename Scheduler::processor_handle processor_handle;
processor_handle my_handle() const
{
return myHandle_;
}
void initiate()
{
initiate_impl();
}
void process_event( const event_base & evt )
{
process_event_impl( evt );
}
void terminate()
{
terminate_impl();
}
protected:
//////////////////////////////////////////////////////////////////////////
typedef const typename Scheduler::processor_context & my_context;
event_processor( my_context ctx ) :
myScheduler_( ctx.my_scheduler() ),
myHandle_( ctx.my_handle() )
{
}
private:
//////////////////////////////////////////////////////////////////////////
virtual void initiate_impl() = 0;
virtual void process_event_impl( const event_base & evt ) = 0;
virtual void terminate_impl() = 0;
// avoids C4512 (assignment operator could not be generated)
event_processor & operator=( const event_processor & );
Scheduler & myScheduler_;
const processor_handle myHandle_;
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,58 @@
#ifndef BOOST_STATECHART_EXCEPTION_TRANSLATOR_HPP_INCLUDED
#define BOOST_STATECHART_EXCEPTION_TRANSLATOR_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/result.hpp>
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
class exception_thrown : public event< exception_thrown > {};
//////////////////////////////////////////////////////////////////////////////
template< class ExceptionEvent = exception_thrown >
class exception_translator
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class Action, class ExceptionEventHandler >
result operator()( Action action, ExceptionEventHandler eventHandler )
{
try
{
return action();
}
catch ( ... )
{
return eventHandler( ExceptionEvent() );
}
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,203 @@
#ifndef BOOST_STATECHART_FIFO_SCHEDULER_HPP_INCLUDED
#define BOOST_STATECHART_FIFO_SCHEDULER_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_base.hpp>
#include <boost/statechart/fifo_worker.hpp>
#include <boost/statechart/processor_container.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/noncopyable.hpp>
#include <boost/config.hpp> // BOOST_HAS_THREADS
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
template<
class FifoWorker = fifo_worker<>,
class Allocator = std::allocator< void > >
class fifo_scheduler : noncopyable
{
typedef processor_container<
fifo_scheduler, typename FifoWorker::work_item, Allocator > container;
public:
//////////////////////////////////////////////////////////////////////////
#ifdef BOOST_HAS_THREADS
fifo_scheduler( bool waitOnEmptyQueue = false ) :
worker_( waitOnEmptyQueue )
{
}
#endif
typedef typename container::processor_handle processor_handle;
typedef typename container::processor_context processor_context;
template< class Processor >
processor_handle create_processor()
{
processor_handle result;
work_item item =
container_.template create_processor< Processor >( result, *this );
worker_.queue_work_item( item );
return result;
}
template< class Processor, typename Arg1 >
processor_handle create_processor( Arg1 arg1 )
{
processor_handle result;
work_item item = container_.template create_processor< Processor >(
result, *this, arg1 );
worker_.queue_work_item( item );
return result;
}
template< class Processor, typename Arg1, typename Arg2 >
processor_handle create_processor( Arg1 arg1, Arg2 arg2 )
{
processor_handle result;
work_item item = container_.template create_processor< Processor >(
result, *this, arg1, arg2 );
worker_.queue_work_item( item );
return result;
}
template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
processor_handle create_processor( Arg1 arg1, Arg2 arg2, Arg3 arg3 )
{
processor_handle result;
work_item item = container_.template create_processor< Processor >(
result, *this, arg1, arg2, arg3 );
worker_.queue_work_item( item );
return result;
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4 >
processor_handle create_processor(
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
{
processor_handle result;
work_item item = container_.template create_processor< Processor >(
result, *this, arg1, arg2, arg3, arg4 );
worker_.queue_work_item( item );
return result;
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5 >
processor_handle create_processor(
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
{
processor_handle result;
work_item item = container_.template create_processor< Processor >(
result, *this, arg1, arg2, arg3, arg4, arg5 );
worker_.queue_work_item( item );
return result;
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
processor_handle create_processor(
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
{
processor_handle result;
work_item item = container_.template create_processor< Processor >(
result, *this, arg1, arg2, arg3, arg4, arg5, arg6 );
worker_.queue_work_item( item );
return result;
}
void destroy_processor( const processor_handle & processor )
{
work_item item = container_.destroy_processor( processor );
worker_.queue_work_item( item );
}
void initiate_processor( const processor_handle & processor )
{
work_item item = container_.initiate_processor( processor );
worker_.queue_work_item( item );
}
void terminate_processor( const processor_handle & processor )
{
work_item item = container_.terminate_processor( processor );
worker_.queue_work_item( item );
}
typedef intrusive_ptr< const event_base > event_ptr_type;
void queue_event(
const processor_handle & processor, const event_ptr_type & pEvent )
{
work_item item = container_.queue_event( processor, pEvent );
worker_.queue_work_item( item );
}
typedef typename FifoWorker::work_item work_item;
// We take a non-const reference so that we can move (i.e. swap) the item
// into the queue, what avoids copying the (possibly heap-allocated)
// implementation object inside work_item.
void queue_work_item( work_item & item )
{
worker_.queue_work_item( item );
}
// Convenience overload so that temporary objects can be passed directly
// instead of having to create a work_item object first. Under most
// circumstances, this will lead to one unnecessary copy of the
// function implementation object.
void queue_work_item( const work_item & item )
{
worker_.queue_work_item( item );
}
void terminate()
{
worker_.terminate();
}
// Is not mutex-protected! Must only be called from the thread that also
// calls operator().
bool terminated() const
{
return worker_.terminated();
}
unsigned long operator()( unsigned long maxEventCount = 0 )
{
return worker_( maxEventCount );
}
private:
//////////////////////////////////////////////////////////////////////////
container container_;
FifoWorker worker_;
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,208 @@
#ifndef BOOST_STATECHART_FIFO_WORKER_HPP_INCLUDED
#define BOOST_STATECHART_FIFO_WORKER_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2008 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/assert.hpp>
#include <boost/noncopyable.hpp>
#include <boost/function/function0.hpp>
#include <boost/bind.hpp>
// BOOST_HAS_THREADS, BOOST_MSVC
#include <boost/config.hpp>
#include <boost/detail/allocator_utilities.hpp>
#ifdef BOOST_HAS_THREADS
# ifdef BOOST_MSVC
# pragma warning( push )
// "conditional expression is constant" in basic_timed_mutex.hpp
# pragma warning( disable: 4127 )
// "conversion from 'int' to 'unsigned short'" in microsec_time_clock.hpp
# pragma warning( disable: 4244 )
// "... needs to have dll-interface to be used by clients of class ..."
# pragma warning( disable: 4251 )
// "... assignment operator could not be generated"
# pragma warning( disable: 4512 )
// "Function call with parameters that may be unsafe" in
// condition_variable.hpp
# pragma warning( disable: 4996 )
# endif
# include <boost/thread/mutex.hpp>
# include <boost/thread/condition.hpp>
# ifdef BOOST_MSVC
# pragma warning( pop )
# endif
#endif
#include <list>
#include <memory> // std::allocator
namespace boost
{
namespace statechart
{
template< class Allocator = std::allocator< void > >
class fifo_worker : noncopyable
{
public:
//////////////////////////////////////////////////////////////////////////
#ifdef BOOST_HAS_THREADS
fifo_worker( bool waitOnEmptyQueue = false ) :
waitOnEmptyQueue_( waitOnEmptyQueue ),
#else
fifo_worker() :
#endif
terminated_( false )
{
}
typedef function0< void > work_item;
// We take a non-const reference so that we can move (i.e. swap) the item
// into the queue, what avoids copying the (possibly heap-allocated)
// implementation object inside work_item.
void queue_work_item( work_item & item )
{
if ( item.empty() )
{
return;
}
#ifdef BOOST_HAS_THREADS
mutex::scoped_lock lock( mutex_ );
#endif
workQueue_.push_back( work_item() );
workQueue_.back().swap( item );
#ifdef BOOST_HAS_THREADS
queueNotEmpty_.notify_one();
#endif
}
// Convenience overload so that temporary objects can be passed directly
// instead of having to create a work_item object first. Under most
// circumstances, this will lead to one unnecessary copy of the
// function implementation object.
void queue_work_item( const work_item & item )
{
work_item copy = item;
queue_work_item( copy );
}
void terminate()
{
work_item item = boost::bind( &fifo_worker::terminate_impl, this );
queue_work_item( item );
}
// Is not mutex-protected! Must only be called from the thread that also
// calls operator().
bool terminated() const
{
return terminated_;
}
unsigned long operator()( unsigned long maxItemCount = 0 )
{
unsigned long itemCount = 0;
while ( !terminated() &&
( ( maxItemCount == 0 ) || ( itemCount < maxItemCount ) ) )
{
work_item item = dequeue_item();
if ( item.empty() )
{
// item can only be empty when the queue is empty, which only
// happens in ST builds or when users pass false to the fifo_worker
// constructor
return itemCount;
}
item();
++itemCount;
}
return itemCount;
}
private:
//////////////////////////////////////////////////////////////////////////
work_item dequeue_item()
{
#ifdef BOOST_HAS_THREADS
mutex::scoped_lock lock( mutex_ );
if ( !waitOnEmptyQueue_ && workQueue_.empty() )
{
return work_item();
}
while ( workQueue_.empty() )
{
queueNotEmpty_.wait( lock );
}
#else
// If the queue happens to run empty in a single-threaded system,
// waiting for new work items (which means to loop indefinitely!) is
// pointless as there is no way that new work items could find their way
// into the queue. The only sensible thing is to exit the loop and
// return to the caller in this case.
// Users can then queue new work items before calling operator() again.
if ( workQueue_.empty() )
{
return work_item();
}
#endif
// Optimization: Swap rather than assign to avoid the copy of the
// implementation object inside function
work_item result;
result.swap( workQueue_.front() );
workQueue_.pop_front();
return result;
}
void terminate_impl()
{
terminated_ = true;
}
typedef std::list<
work_item,
typename boost::detail::allocator::rebind_to<
Allocator, work_item >::type
> work_queue_type;
work_queue_type workQueue_;
#ifdef BOOST_HAS_THREADS
mutex mutex_;
condition queueNotEmpty_;
const bool waitOnEmptyQueue_;
#endif
bool terminated_;
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,16 @@
#ifndef BOOST_STATECHART_HISTORY_HPP_INCLUDED
#define BOOST_STATECHART_HISTORY_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/shallow_history.hpp>
#include <boost/statechart/deep_history.hpp>
#endif

View File

@@ -0,0 +1,73 @@
#ifndef BOOST_STATECHART_IN_STATE_REACTION_HPP_INCLUDED
#define BOOST_STATECHART_IN_STATE_REACTION_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2005-2008 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/result.hpp>
#include <boost/statechart/detail/reaction_dispatcher.hpp>
namespace boost
{
namespace statechart
{
class event_base;
//////////////////////////////////////////////////////////////////////////////
template< class Event,
class ReactionContext = detail::no_context< Event >,
void ( ReactionContext::*pAction )( const Event & ) =
&detail::no_context< Event >::no_function >
class in_state_reaction
{
private:
//////////////////////////////////////////////////////////////////////////
template< class State >
struct reactions
{
static result react_without_action( State & stt )
{
return stt.discard_event();
}
static result react_with_action( State & stt, const Event & evt )
{
( stt.template context< ReactionContext >().*pAction )( evt );
return react_without_action( stt );
}
};
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase & evt, const IdType & eventType )
{
typedef detail::reaction_dispatcher<
reactions< State >, State, EventBase, Event, ReactionContext, IdType
> dispatcher;
return dispatcher::react( stt, evt, eventType );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,44 @@
#ifndef BOOST_STATECHART_NULL_EXCEPTION_TRANSLATOR_HPP_INCLUDED
#define BOOST_STATECHART_NULL_EXCEPTION_TRANSLATOR_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/result.hpp>
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
class null_exception_translator
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class Action, class ExceptionEventHandler >
result operator()( Action action, ExceptionEventHandler )
{
return action();
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,445 @@
#ifndef BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
#define BOOST_STATECHART_PROCESSOR_CONTAINER_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2008 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_base.hpp>
#include <boost/statechart/event_processor.hpp>
#include <boost/assert.hpp>
#include <boost/ref.hpp>
#include <boost/noncopyable.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/shared_ptr.hpp>
#include <boost/weak_ptr.hpp>
#include <boost/bind.hpp>
#include <boost/config.hpp> // BOOST_INTEL
#include <boost/detail/workaround.hpp>
#include <boost/detail/allocator_utilities.hpp>
#include <set>
#include <memory> // std::allocator, std::auto_ptr
namespace boost
{
namespace statechart
{
namespace detail
{
template<bool IsReferenceWrapper>
struct unwrap_impl
{
template< typename T >
struct apply { typedef T type; };
};
template<>
struct unwrap_impl<true>
{
template< typename T >
struct apply { typedef typename T::type & type; };
};
template<typename T>
struct unwrap
{
typedef typename unwrap_impl<
is_reference_wrapper< T >::value >::template apply< T >::type type;
};
}
template<
class Scheduler,
class WorkItem,
class Allocator = std::allocator< void > >
class processor_container : noncopyable
{
typedef event_processor< Scheduler > processor_base_type;
typedef std::auto_ptr< processor_base_type > processor_holder_type;
typedef shared_ptr< processor_holder_type > processor_holder_ptr_type;
public:
//////////////////////////////////////////////////////////////////////////
typedef weak_ptr< processor_holder_type > processor_handle;
class processor_context
{
processor_context(
Scheduler & scheduler, const processor_handle & handle
) :
scheduler_( scheduler ),
handle_( handle )
{
}
#if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
public:
// for some reason Intel 8.0 seems to think that the following functions
// are inaccessible from event_processor<>::event_processor
#endif
Scheduler & my_scheduler() const { return scheduler_; }
const processor_handle & my_handle() const { return handle_; }
#if BOOST_WORKAROUND( BOOST_INTEL, BOOST_TESTED_AT( 800 ) )
private:
#endif
// avoids C4512 (assignment operator could not be generated)
processor_context & operator=( const processor_context & );
Scheduler & scheduler_;
const processor_handle handle_;
friend class processor_container;
friend class event_processor< Scheduler >;
};
template< class Processor >
WorkItem create_processor( processor_handle & handle, Scheduler & scheduler )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context & );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl0< Processor >;
return WorkItem(
boost::bind( pImpl, this, pProcessor,
processor_context( scheduler, handle ) ),
Allocator() );
}
template< class Processor, typename Arg1 >
WorkItem create_processor(
processor_handle & handle, Scheduler & scheduler, Arg1 arg1 )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef typename detail::unwrap< Arg1 >::type arg1_type;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context &,
arg1_type );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl1<
Processor, arg1_type >;
return WorkItem(
boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
arg1 ),
Allocator() );
}
template< class Processor, typename Arg1, typename Arg2 >
WorkItem create_processor(
processor_handle & handle, Scheduler & scheduler, Arg1 arg1, Arg2 arg2 )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef typename detail::unwrap< Arg1 >::type arg1_type;
typedef typename detail::unwrap< Arg2 >::type arg2_type;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context &,
arg1_type, arg2_type );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl2<
Processor, arg1_type, arg2_type >;
return WorkItem(
boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
arg1, arg2 ),
Allocator() );
}
template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
WorkItem create_processor(
processor_handle & handle, Scheduler & scheduler,
Arg1 arg1, Arg2 arg2, Arg3 arg3 )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef typename detail::unwrap< Arg1 >::type arg1_type;
typedef typename detail::unwrap< Arg2 >::type arg2_type;
typedef typename detail::unwrap< Arg3 >::type arg3_type;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context &,
arg1_type, arg2_type, arg3_type );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl3<
Processor, arg1_type, arg2_type, arg3_type >;
return WorkItem(
boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
arg1, arg2, arg3 ),
Allocator() );
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4 >
WorkItem create_processor(
processor_handle & handle, Scheduler & scheduler,
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef typename detail::unwrap< Arg1 >::type arg1_type;
typedef typename detail::unwrap< Arg2 >::type arg2_type;
typedef typename detail::unwrap< Arg3 >::type arg3_type;
typedef typename detail::unwrap< Arg4 >::type arg4_type;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context &,
arg1_type, arg2_type, arg3_type, arg4_type );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl4<
Processor, arg1_type, arg2_type, arg3_type, arg4_type >;
return WorkItem(
boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
arg1, arg2, arg3, arg4 ),
Allocator() );
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5 >
WorkItem create_processor(
processor_handle & handle, Scheduler & scheduler,
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef typename detail::unwrap< Arg1 >::type arg1_type;
typedef typename detail::unwrap< Arg2 >::type arg2_type;
typedef typename detail::unwrap< Arg3 >::type arg3_type;
typedef typename detail::unwrap< Arg4 >::type arg4_type;
typedef typename detail::unwrap< Arg5 >::type arg5_type;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context &,
arg1_type, arg2_type, arg3_type, arg4_type, arg5_type );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl5<
Processor, arg1_type, arg2_type, arg3_type, arg4_type, arg5_type >;
return WorkItem(
boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
arg1, arg2, arg3, arg4, arg5 ),
Allocator() );
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
WorkItem create_processor(
processor_handle & handle, Scheduler & scheduler,
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
{
processor_holder_ptr_type pProcessor = make_processor_holder();
handle = pProcessor;
typedef typename detail::unwrap< Arg1 >::type arg1_type;
typedef typename detail::unwrap< Arg2 >::type arg2_type;
typedef typename detail::unwrap< Arg3 >::type arg3_type;
typedef typename detail::unwrap< Arg4 >::type arg4_type;
typedef typename detail::unwrap< Arg5 >::type arg5_type;
typedef typename detail::unwrap< Arg6 >::type arg6_type;
typedef void ( processor_container::*impl_fun_ptr )(
const processor_holder_ptr_type &, const processor_context &,
arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type );
impl_fun_ptr pImpl =
&processor_container::template create_processor_impl6<
Processor,
arg1_type, arg2_type, arg3_type, arg4_type, arg5_type, arg6_type >;
return WorkItem(
boost::bind( pImpl, this, pProcessor, processor_context( scheduler, handle ),
arg1, arg2, arg3, arg4, arg5, arg6 ),
Allocator() );
}
WorkItem destroy_processor( const processor_handle & processor )
{
return WorkItem(
boost::bind( &processor_container::destroy_processor_impl, this, processor ),
Allocator() );
}
WorkItem initiate_processor( const processor_handle & processor )
{
return WorkItem(
boost::bind( &processor_container::initiate_processor_impl, this,
processor ),
Allocator() );
}
WorkItem terminate_processor( const processor_handle & processor )
{
return WorkItem(
boost::bind( &processor_container::terminate_processor_impl, this,
processor ),
Allocator() );
}
typedef intrusive_ptr< const event_base > event_ptr_type;
WorkItem queue_event(
const processor_handle & processor, const event_ptr_type & pEvent )
{
BOOST_ASSERT( pEvent.get() != 0 );
return WorkItem(
boost::bind( &processor_container::queue_event_impl, this, processor,
pEvent ),
Allocator() );
}
private:
//////////////////////////////////////////////////////////////////////////
processor_holder_ptr_type make_processor_holder()
{
return processor_holder_ptr_type( new processor_holder_type() );
}
template< class Processor >
void create_processor_impl0(
const processor_holder_ptr_type & pProcessor,
const processor_context & context )
{
processorSet_.insert( pProcessor );
processor_holder_type holder( new Processor( context ) );
*pProcessor = holder;
}
template< class Processor, typename Arg1 >
void create_processor_impl1(
const processor_holder_ptr_type & pProcessor,
const processor_context & context, Arg1 arg1 )
{
processorSet_.insert( pProcessor );
processor_holder_type holder( new Processor( context, arg1 ) );
*pProcessor = holder;
}
template< class Processor, typename Arg1, typename Arg2 >
void create_processor_impl2(
const processor_holder_ptr_type & pProcessor,
const processor_context & context, Arg1 arg1, Arg2 arg2 )
{
processorSet_.insert( pProcessor );
processor_holder_type holder( new Processor( context, arg1, arg2 ) );
*pProcessor = holder;
}
template< class Processor, typename Arg1, typename Arg2, typename Arg3 >
void create_processor_impl3(
const processor_holder_ptr_type & pProcessor,
const processor_context & context, Arg1 arg1, Arg2 arg2, Arg3 arg3 )
{
processorSet_.insert( pProcessor );
processor_holder_type holder(
new Processor( context, arg1, arg2, arg3 ) );
*pProcessor = holder;
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4 >
void create_processor_impl4(
const processor_holder_ptr_type & pProcessor,
const processor_context & context,
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4 )
{
processorSet_.insert( pProcessor );
processor_holder_type holder(
new Processor( context, arg1, arg2, arg3, arg4 ) );
*pProcessor = holder;
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5 >
void create_processor_impl5(
const processor_holder_ptr_type & pProcessor,
const processor_context & context,
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5 )
{
processorSet_.insert( pProcessor );
processor_holder_type holder(
new Processor( context, arg1, arg2, arg3, arg4, arg5 ) );
*pProcessor = holder;
}
template<
class Processor, typename Arg1, typename Arg2,
typename Arg3, typename Arg4, typename Arg5, typename Arg6 >
void create_processor_impl6(
const processor_holder_ptr_type & pProcessor,
const processor_context & context,
Arg1 arg1, Arg2 arg2, Arg3 arg3, Arg4 arg4, Arg5 arg5, Arg6 arg6 )
{
processorSet_.insert( pProcessor );
processor_holder_type holder(
new Processor( context, arg1, arg2, arg3, arg4, arg5, arg6 ) );
*pProcessor = holder;
}
void destroy_processor_impl( const processor_handle & processor )
{
const processor_holder_ptr_type pProcessor = processor.lock();
if ( pProcessor != 0 )
{
processorSet_.erase( pProcessor );
}
}
void initiate_processor_impl( const processor_handle & processor )
{
const processor_holder_ptr_type pProcessor = processor.lock();
if ( pProcessor != 0 )
{
( *pProcessor )->initiate();
}
}
void terminate_processor_impl( const processor_handle & processor )
{
const processor_holder_ptr_type pProcessor = processor.lock();
if ( pProcessor != 0 )
{
( *pProcessor )->terminate();
}
}
void queue_event_impl(
const processor_handle & processor, const event_ptr_type & pEvent )
{
const processor_holder_ptr_type pProcessor = processor.lock();
if ( pProcessor != 0 )
{
( *pProcessor )->process_event( *pEvent );
}
}
typedef std::set<
processor_holder_ptr_type,
std::less< processor_holder_ptr_type >,
typename boost::detail::allocator::rebind_to<
Allocator, processor_holder_ptr_type >::type
> event_processor_set_type;
event_processor_set_type processorSet_;
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,122 @@
#ifndef BOOST_STATECHART_RESULT_HPP_INCLUDED
#define BOOST_STATECHART_RESULT_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2010 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/assert.hpp>
namespace boost
{
namespace statechart
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
enum reaction_result
{
no_reaction,
do_forward_event,
do_discard_event,
do_defer_event,
consumed
};
struct result_utility;
//////////////////////////////////////////////////////////////////////////////
class safe_reaction_result
{
public:
//////////////////////////////////////////////////////////////////////////
safe_reaction_result( const safe_reaction_result & other ) :
reactionResult_( other.reactionResult_ )
{
// This assert fails when an attempt is made to make multiple copies of
// a result value. This makes little sense, given the requirement that
// an obtained result value must be returned out of the react function.
BOOST_ASSERT( reactionResult_ != consumed );
other.reactionResult_ = consumed;
}
~safe_reaction_result()
{
// This assert fails when an obtained result value is not returned out
// of the react() function. This can happen if the user accidentally
// makes more than one call to reaction functions inside react() or
// accidentally makes one or more calls to reaction functions outside
// react()
BOOST_ASSERT( reactionResult_ == consumed );
}
private:
//////////////////////////////////////////////////////////////////////////
safe_reaction_result( reaction_result reactionResult ) :
reactionResult_( reactionResult )
{
}
operator reaction_result() const
{
const reaction_result val = reactionResult_;
reactionResult_ = consumed;
return val;
}
safe_reaction_result & operator=( const safe_reaction_result & );
mutable reaction_result reactionResult_;
friend struct result_utility;
};
} // namespace detail
#ifdef NDEBUG
typedef detail::reaction_result result;
#else
typedef detail::safe_reaction_result result;
#endif
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
struct result_utility
{
static ::boost::statechart::result make_result( reaction_result value )
{
return value;
}
static reaction_result get_result( ::boost::statechart::result value )
{
return value;
}
};
} // namespace detail
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,63 @@
#ifndef BOOST_STATECHART_SHALLOW_HISTORY_HPP_INCLUDED
#define BOOST_STATECHART_SHALLOW_HISTORY_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/mpl/bool.hpp>
#include <boost/static_assert.hpp>
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
template< class DefaultState >
class shallow_history
{
public:
//////////////////////////////////////////////////////////////////////////
// If you receive a
// "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
// compiler error here then you forgot to pass either
// statechart::has_deep_history or statechart::has_full_history as the
// last parameter of DefaultState's context.
BOOST_STATIC_ASSERT( DefaultState::context_type::shallow_history::value );
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
typedef typename DefaultState::outermost_context_base_type
outermost_context_base_type;
typedef typename DefaultState::context_type context_type;
typedef typename DefaultState::context_ptr_type context_ptr_type;
typedef typename DefaultState::context_type_list context_type_list;
typedef typename DefaultState::orthogonal_position orthogonal_position;
static void deep_construct(
const context_ptr_type & pContext,
outermost_context_base_type & outermostContextBase )
{
outermostContextBase.template construct_with_shallow_history<
DefaultState >( pContext );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,998 @@
#ifndef BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED
#define BOOST_STATECHART_SIMPLE_STATE_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2010 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/detail/leaf_state.hpp>
#include <boost/statechart/detail/node_state.hpp>
#include <boost/statechart/detail/constructor.hpp>
#include <boost/statechart/detail/memory.hpp>
#include <boost/mpl/eval_if.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/identity.hpp>
#include <boost/mpl/is_sequence.hpp>
#include <boost/mpl/list.hpp>
#include <boost/mpl/empty.hpp>
#include <boost/mpl/size.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/at.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/find_if.hpp>
#include <boost/mpl/contains.hpp>
#include <boost/mpl/distance.hpp>
#include <boost/mpl/deref.hpp>
#include <boost/mpl/pop_front.hpp>
#include <boost/mpl/push_front.hpp>
#include <boost/mpl/clear.hpp>
#include <boost/mpl/placeholders.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/integral_c.hpp>
#include <boost/mpl/less.hpp>
#include <boost/mpl/equal_to.hpp>
#include <boost/mpl/not.hpp>
#include <boost/mpl/or.hpp>
#include <boost/mpl/plus.hpp>
#include <boost/mpl/max_element.hpp>
#include <boost/mpl/greater.hpp>
#include <boost/get_pointer.hpp>
#include <boost/intrusive_ptr.hpp>
#include <boost/assert.hpp>
#include <boost/type_traits/is_base_of.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/static_assert.hpp>
#include <boost/cast.hpp> // boost::polymorphic_downcast
#include <cstddef> // std::size_t
namespace boost
{
namespace statechart
{
namespace detail
{
//////////////////////////////////////////////////////////////////////////////
template< class T >
struct make_list : public mpl::eval_if<
mpl::is_sequence< T >,
mpl::identity< T >,
mpl::identity< mpl::list< T > > > {};
//////////////////////////////////////////////////////////////////////////////
template< class MostDerived, class Context, class InnerInitial >
struct simple_state_base_type
{
private:
typedef typename Context::outermost_context_base_type::allocator_type
allocator_type;
typedef typename Context::outermost_context_base_type::rtti_policy_type
rtti_policy_type;
typedef typename detail::make_list< InnerInitial >::type
inner_initial_list;
typedef typename mpl::size< inner_initial_list >::type
inner_initial_list_size;
public:
typedef typename mpl::eval_if<
mpl::empty< inner_initial_list >,
mpl::identity< typename rtti_policy_type::
template rtti_derived_type< MostDerived, leaf_state<
allocator_type,
rtti_policy_type > > >,
mpl::identity< typename rtti_policy_type::
template rtti_derived_type< MostDerived, node_state<
inner_initial_list_size,
allocator_type,
rtti_policy_type > > > >::type type;
};
//////////////////////////////////////////////////////////////////////////////
struct no_transition_function
{
template< class CommonContext >
void operator()( CommonContext & ) const {}
};
template< class TransitionContext, class Event >
class transition_function
{
public:
transition_function(
void ( TransitionContext::*pTransitionAction )( const Event & ),
const Event & evt
) :
pTransitionAction_( pTransitionAction ),
evt_( evt )
{
}
template< class CommonContext >
void operator()( CommonContext & commonContext ) const
{
( commonContext.template context< TransitionContext >()
.*pTransitionAction_ )( evt_ );
}
private:
// avoids C4512 (assignment operator could not be generated)
transition_function & operator=( const transition_function & );
void ( TransitionContext::*pTransitionAction_ )( const Event & );
const Event & evt_;
};
template< bool contextHasInheritedDeepHistory, bool contextHasDeepHistory >
struct deep_history_storer
{
template< class HistorizedState, class LeafState, class Context >
static void store_deep_history( Context & ) {}
};
template<>
struct deep_history_storer< true, false >
{
template< class HistorizedState, class LeafState, class Context >
static void store_deep_history( Context & ctx )
{
ctx.template store_deep_history_impl< LeafState >();
}
};
template<>
struct deep_history_storer< true, true >
{
template< class HistorizedState, class LeafState, class Context >
static void store_deep_history( Context & ctx )
{
ctx.outermost_context_base().template store_deep_history<
HistorizedState, LeafState >();
ctx.template store_deep_history_impl< LeafState >();
}
};
} // namespace detail
//////////////////////////////////////////////////////////////////////////////
enum history_mode
{
has_no_history,
has_shallow_history,
has_deep_history,
has_full_history // shallow & deep
};
//////////////////////////////////////////////////////////////////////////////
template< class MostDerived,
class Context,
class InnerInitial = mpl::list<>,
history_mode historyMode = has_no_history >
class simple_state : public detail::simple_state_base_type< MostDerived,
typename Context::inner_context_type, InnerInitial >::type
{
typedef typename detail::simple_state_base_type<
MostDerived, typename Context::inner_context_type,
InnerInitial >::type base_type;
public:
//////////////////////////////////////////////////////////////////////////
typedef mpl::list<> reactions;
typedef typename Context::inner_context_type context_type;
template< detail::orthogonal_position_type innerOrthogonalPosition >
struct orthogonal
{
typedef mpl::integral_c<
detail::orthogonal_position_type,
innerOrthogonalPosition > inner_orthogonal_position;
typedef MostDerived inner_context_type;
};
typedef typename context_type::outermost_context_type
outermost_context_type;
outermost_context_type & outermost_context()
{
// This assert fails when an attempt is made to access the state machine
// from a constructor of a state that is *not* a subtype of state<>.
// To correct this, derive from state<> instead of simple_state<>.
BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
return pContext_->outermost_context();
}
const outermost_context_type & outermost_context() const
{
// This assert fails when an attempt is made to access the state machine
// from a constructor of a state that is *not* a subtype of state<>.
// To correct this, derive from state<> instead of simple_state<>.
BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
return pContext_->outermost_context();
}
template< class OtherContext >
OtherContext & context()
{
typedef typename mpl::if_<
is_base_of< OtherContext, MostDerived >,
context_impl_this_context,
context_impl_other_context
>::type impl;
return impl::template context_impl< OtherContext >( *this );
}
template< class OtherContext >
const OtherContext & context() const
{
typedef typename mpl::if_<
is_base_of< OtherContext, MostDerived >,
context_impl_this_context,
context_impl_other_context
>::type impl;
return impl::template context_impl< OtherContext >( *this );
}
template< class Target >
Target state_cast() const
{
return outermost_context_base().template state_cast< Target >();
}
template< class Target >
Target state_downcast() const
{
return outermost_context_base().template state_downcast< Target >();
}
typedef typename context_type::state_base_type state_base_type;
typedef typename context_type::state_iterator state_iterator;
state_iterator state_begin() const
{
return outermost_context_base().state_begin();
}
state_iterator state_end() const
{
return outermost_context_base().state_end();
}
typedef typename context_type::event_base_ptr_type event_base_ptr_type;
void post_event( const event_base_ptr_type & pEvent )
{
outermost_context_base().post_event_impl( pEvent );
}
void post_event( const event_base & evt )
{
outermost_context_base().post_event_impl( evt );
}
result discard_event()
{
return detail::result_utility::make_result( detail::do_discard_event );
}
result forward_event()
{
return detail::result_utility::make_result( detail::do_forward_event );
}
result defer_event()
{
this->state_base_type::defer_event();
return detail::result_utility::make_result( detail::do_defer_event );
}
template< class DestinationState >
result transit()
{
return transit_impl< DestinationState, outermost_context_type >(
detail::no_transition_function() );
}
template< class DestinationState, class TransitionContext, class Event >
result transit(
void ( TransitionContext::*pTransitionAction )( const Event & ),
const Event & evt )
{
return transit_impl< DestinationState, TransitionContext >(
detail::transition_function< TransitionContext, Event >(
pTransitionAction, evt ) );
}
result terminate()
{
outermost_context_base().terminate_as_reaction( *this );
return detail::result_utility::make_result( detail::do_discard_event );
}
template<
class HistoryContext,
detail::orthogonal_position_type orthogonalPosition >
void clear_shallow_history()
{
outermost_context_base().template clear_shallow_history<
HistoryContext, orthogonalPosition >();
}
template<
class HistoryContext,
detail::orthogonal_position_type orthogonalPosition >
void clear_deep_history()
{
outermost_context_base().template clear_deep_history<
HistoryContext, orthogonalPosition >();
}
const event_base * triggering_event() const
{
return outermost_context_base().triggering_event();
}
protected:
//////////////////////////////////////////////////////////////////////////
simple_state() : pContext_( 0 ) {}
~simple_state()
{
// As a result of a throwing derived class constructor, this destructor
// can be called before the context is set.
if ( get_pointer( pContext_ ) != 0 )
{
if ( this->deferred_events() )
{
outermost_context_base().release_events();
}
pContext_->remove_inner_state( orthogonal_position::value );
}
}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
typedef typename Context::inner_orthogonal_position orthogonal_position;
// If you receive a
// "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
// compiler error here then either this state resides in a non-existent
// orthogonal region of the outer state or the outer state does not have
// inner states.
BOOST_STATIC_ASSERT( ( mpl::less<
orthogonal_position,
typename context_type::no_of_orthogonal_regions >::value ) );
typedef MostDerived inner_context_type;
typedef mpl::integral_c< detail::orthogonal_position_type, 0 >
inner_orthogonal_position;
typedef typename context_type::event_base_type event_base_type;
typedef typename context_type::rtti_policy_type rtti_policy_type;
typedef typename context_type::outermost_context_base_type
outermost_context_base_type;
typedef typename context_type::inner_context_ptr_type context_ptr_type;
typedef typename context_type::state_list_type state_list_type;
typedef intrusive_ptr< inner_context_type > inner_context_ptr_type;
typedef typename detail::make_list< InnerInitial >::type
inner_initial_list;
typedef typename mpl::size< inner_initial_list >::type
inner_initial_list_size;
typedef mpl::integral_c<
detail::orthogonal_position_type,
inner_initial_list_size::value > no_of_orthogonal_regions;
typedef typename mpl::push_front<
typename context_type::context_type_list,
context_type >::type context_type_list;
// If you receive a
// "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or similar
// compiler error here then the direct or indirect context of this state
// has deep history _and_ this state has two or more orthogonal regions.
// Boost.Statechart does not currently support deep history in a state whose
// direct or indirect inner states have two or more orthogonal regions.
// Please consult the documentation on how to work around this limitation.
BOOST_STATIC_ASSERT( ( mpl::or_<
mpl::less<
no_of_orthogonal_regions,
mpl::integral_c< detail::orthogonal_position_type, 2 > >,
mpl::not_<
typename context_type::inherited_deep_history > >::value ) );
typedef mpl::bool_< ( historyMode & has_shallow_history ) != 0 >
shallow_history;
typedef typename context_type::shallow_history stores_shallow_history;
typedef mpl::bool_< ( historyMode & has_deep_history ) != 0 >
deep_history;
typedef typename mpl::or_<
deep_history,
typename context_type::inherited_deep_history
>::type inherited_deep_history;
typedef typename mpl::and_<
inherited_deep_history,
mpl::empty< inner_initial_list > >::type stores_deep_history;
void * operator new( std::size_t size )
{
return detail::allocate< MostDerived,
typename outermost_context_type::allocator_type >( size );
}
void operator delete( void * pState )
{
detail::deallocate< MostDerived,
typename outermost_context_type::allocator_type >( pState );
}
outermost_context_base_type & outermost_context_base()
{
// This assert fails when an attempt is made to access the state machine
// from a constructor of a state that is *not* a subtype of state<>.
// To correct this, derive from state<> instead of simple_state<>.
BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
return pContext_->outermost_context_base();
}
const outermost_context_base_type & outermost_context_base() const
{
// This assert fails when an attempt is made to access the state machine
// from a constructor of a state that is *not* a subtype of state<>.
// To correct this, derive from state<> instead of simple_state<>.
BOOST_ASSERT( get_pointer( pContext_ ) != 0 );
return pContext_->outermost_context_base();
}
virtual const state_base_type * outer_state_ptr() const
{
typedef typename mpl::if_<
is_same< outermost_context_type, context_type >,
outer_state_ptr_impl_outermost,
outer_state_ptr_impl_non_outermost
>::type impl;
return impl::outer_state_ptr_impl( *this );
}
virtual detail::reaction_result react_impl(
const event_base_type & evt,
typename rtti_policy_type::id_type eventType )
{
typedef typename detail::make_list<
typename MostDerived::reactions >::type reaction_list;
detail::reaction_result reactionResult =
local_react< reaction_list >( evt, eventType );
// At this point we can only safely access pContext_ if the handler did
// not return do_discard_event!
if ( reactionResult == detail::do_forward_event )
{
// TODO: The following call to react_impl of our outer state should
// be made with a context_type:: prefix to call directly instead of
// virtually. For some reason the compiler complains...
reactionResult = pContext_->react_impl( evt, eventType );
}
return reactionResult;
}
virtual void exit_impl(
typename base_type::direct_state_base_ptr_type & pSelf,
typename state_base_type::node_state_base_ptr_type &
pOutermostUnstableState,
bool performFullExit )
{
inner_context_ptr_type pMostDerivedSelf =
polymorphic_downcast< MostDerived * >( this );
pSelf = 0;
exit_impl( pMostDerivedSelf, pOutermostUnstableState, performFullExit );
}
void exit_impl(
inner_context_ptr_type & pSelf,
typename state_base_type::node_state_base_ptr_type &
pOutermostUnstableState,
bool performFullExit )
{
switch ( this->ref_count() )
{
case 2:
if ( get_pointer( pOutermostUnstableState ) ==
static_cast< state_base_type * >( this ) )
{
pContext_->set_outermost_unstable_state(
pOutermostUnstableState );
// fall through to next case intended
}
else
{
break;
}
case 1:
{
if ( get_pointer( pOutermostUnstableState ) == 0 )
{
pContext_->set_outermost_unstable_state(
pOutermostUnstableState );
}
if ( performFullExit )
{
pSelf->exit();
check_store_shallow_history< stores_shallow_history >();
check_store_deep_history< stores_deep_history >();
}
context_ptr_type pContext = pContext_;
pSelf = 0;
pContext->exit_impl(
pContext, pOutermostUnstableState, performFullExit );
break;
}
default:
break;
}
}
void set_outermost_unstable_state(
typename state_base_type::node_state_base_ptr_type &
pOutermostUnstableState )
{
pOutermostUnstableState = this;
}
template< class OtherContext >
const typename OtherContext::inner_context_ptr_type & context_ptr() const
{
typedef typename mpl::if_<
is_same< OtherContext, context_type >,
context_ptr_impl_my_context,
context_ptr_impl_other_context
>::type impl;
return impl::template context_ptr_impl< OtherContext >( *this );
}
static void initial_deep_construct(
outermost_context_base_type & outermostContextBase )
{
deep_construct( &outermostContextBase, outermostContextBase );
}
static void deep_construct(
const context_ptr_type & pContext,
outermost_context_base_type & outermostContextBase )
{
const inner_context_ptr_type pInnerContext(
shallow_construct( pContext, outermostContextBase ) );
deep_construct_inner< inner_initial_list >(
pInnerContext, outermostContextBase );
}
static inner_context_ptr_type shallow_construct(
const context_ptr_type & pContext,
outermost_context_base_type & outermostContextBase )
{
const inner_context_ptr_type pInnerContext( new MostDerived );
pInnerContext->set_context( pContext );
outermostContextBase.add( pInnerContext );
return pInnerContext;
}
void set_context( const context_ptr_type & pContext )
{
BOOST_ASSERT( get_pointer( pContext ) != 0 );
pContext_ = pContext;
base_type::set_context(
orthogonal_position::value, get_pointer( pContext ) );
}
template< class InnerList >
static void deep_construct_inner(
const inner_context_ptr_type & pInnerContext,
outermost_context_base_type & outermostContextBase )
{
typedef typename mpl::if_<
mpl::empty< InnerList >,
deep_construct_inner_impl_empty,
deep_construct_inner_impl_non_empty
>::type impl;
impl::template deep_construct_inner_impl< InnerList >(
pInnerContext, outermostContextBase );
}
template< class LeafState >
void store_deep_history_impl()
{
detail::deep_history_storer<
context_type::inherited_deep_history::value,
context_type::deep_history::value
>::template store_deep_history< MostDerived, LeafState >(
*pContext_ );
}
private:
//////////////////////////////////////////////////////////////////////////
struct context_ptr_impl_other_context
{
template< class OtherContext, class State >
static const typename OtherContext::inner_context_ptr_type &
context_ptr_impl( const State & stt )
{
// This assert fails when an attempt is made to access an outer
// context from a constructor of a state that is *not* a subtype of
// state<>. To correct this, derive from state<> instead of
// simple_state<>.
BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
return stt.pContext_->template context_ptr< OtherContext >();
}
};
friend struct context_ptr_impl_other_context;
struct context_ptr_impl_my_context
{
template< class OtherContext, class State >
static const typename OtherContext::inner_context_ptr_type &
context_ptr_impl( const State & stt )
{
// This assert fails when an attempt is made to access an outer
// context from a constructor of a state that is *not* a subtype of
// state<>. To correct this, derive from state<> instead of
// simple_state<>.
BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
return stt.pContext_;
}
};
friend struct context_ptr_impl_my_context;
struct context_impl_other_context
{
template< class OtherContext, class State >
static OtherContext & context_impl( State & stt )
{
// This assert fails when an attempt is made to access an outer
// context from a constructor of a state that is *not* a subtype of
// state<>. To correct this, derive from state<> instead of
// simple_state<>.
BOOST_ASSERT( get_pointer( stt.pContext_ ) != 0 );
return stt.pContext_->template context< OtherContext >();
}
};
friend struct context_impl_other_context;
struct context_impl_this_context
{
template< class OtherContext, class State >
static OtherContext & context_impl( State & stt )
{
return *polymorphic_downcast< MostDerived * >( &stt );
}
};
friend struct context_impl_this_context;
template< class DestinationState,
class TransitionContext,
class TransitionAction >
result transit_impl( const TransitionAction & transitionAction )
{
typedef typename mpl::find_if<
context_type_list,
mpl::contains<
typename DestinationState::context_type_list,
mpl::placeholders::_ > >::type common_context_iter;
typedef typename mpl::deref< common_context_iter >::type
common_context_type;
typedef typename mpl::distance<
typename mpl::begin< context_type_list >::type,
common_context_iter >::type termination_state_position;
typedef typename mpl::push_front< context_type_list, MostDerived >::type
possible_transition_contexts;
typedef typename mpl::at<
possible_transition_contexts,
termination_state_position >::type termination_state_type;
termination_state_type & terminationState(
context< termination_state_type >() );
const typename
common_context_type::inner_context_ptr_type pCommonContext(
terminationState.template context_ptr< common_context_type >() );
outermost_context_base_type & outermostContextBase(
pCommonContext->outermost_context_base() );
#ifdef BOOST_STATECHART_RELAX_TRANSITION_CONTEXT
typedef typename mpl::distance<
typename mpl::begin< possible_transition_contexts >::type,
typename mpl::find<
possible_transition_contexts, TransitionContext >::type
>::type proposed_transition_context_position;
typedef typename mpl::plus<
termination_state_position,
mpl::long_< 1 >
>::type uml_transition_context_position;
typedef typename mpl::deref< typename mpl::max_element<
mpl::list<
proposed_transition_context_position,
uml_transition_context_position >,
mpl::greater< mpl::placeholders::_, mpl::placeholders::_ >
>::type >::type real_transition_context_position;
typedef typename mpl::at<
possible_transition_contexts,
real_transition_context_position >::type real_transition_context_type;
#ifdef BOOST_MSVC
# pragma warning( push )
# pragma warning( disable: 4127 ) // conditional expression is constant
#endif
if ( ( proposed_transition_context_position::value == 0 ) &&
( inner_initial_list_size::value == 0 ) )
{
transitionAction( *polymorphic_downcast< MostDerived * >( this ) );
outermostContextBase.terminate_as_part_of_transit( terminationState );
}
else if ( proposed_transition_context_position::value >=
uml_transition_context_position::value )
{
real_transition_context_type & transitionContext =
context< real_transition_context_type >();
outermostContextBase.terminate_as_part_of_transit( terminationState );
transitionAction( transitionContext );
}
else
{
typename real_transition_context_type::inner_context_ptr_type
pTransitionContext = context_ptr< real_transition_context_type >();
outermostContextBase.terminate_as_part_of_transit(
*pTransitionContext );
transitionAction( *pTransitionContext );
pTransitionContext = 0;
outermostContextBase.terminate_as_part_of_transit( terminationState );
}
#ifdef BOOST_MSVC
# pragma warning( pop )
#endif
#else
outermostContextBase.terminate_as_part_of_transit( terminationState );
transitionAction( *pCommonContext );
#endif
typedef typename detail::make_context_list<
common_context_type, DestinationState >::type context_list_type;
// If you receive a
// "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
// similar compiler error here then you tried to make an invalid
// transition between different orthogonal regions.
BOOST_STATIC_ASSERT( ( mpl::equal_to<
typename termination_state_type::orthogonal_position,
typename mpl::front< context_list_type >::type::orthogonal_position
>::value ) );
detail::constructor<
context_list_type, outermost_context_base_type >::construct(
pCommonContext, outermostContextBase );
return detail::result_utility::make_result( detail::do_discard_event );
}
struct local_react_impl_non_empty
{
template< class ReactionList, class State >
static detail::reaction_result local_react_impl(
State & stt,
const event_base_type & evt,
typename rtti_policy_type::id_type eventType )
{
detail::reaction_result reactionResult =
mpl::front< ReactionList >::type::react(
*polymorphic_downcast< MostDerived * >( &stt ),
evt, eventType );
if ( reactionResult == detail::no_reaction )
{
reactionResult = stt.template local_react<
typename mpl::pop_front< ReactionList >::type >(
evt, eventType );
}
return reactionResult;
}
};
friend struct local_react_impl_non_empty;
struct local_react_impl_empty
{
template< class ReactionList, class State >
static detail::reaction_result local_react_impl(
State &, const event_base_type &, typename rtti_policy_type::id_type )
{
return detail::do_forward_event;
}
};
template< class ReactionList >
detail::reaction_result local_react(
const event_base_type & evt,
typename rtti_policy_type::id_type eventType )
{
typedef typename mpl::if_<
mpl::empty< ReactionList >,
local_react_impl_empty,
local_react_impl_non_empty
>::type impl;
return impl::template local_react_impl< ReactionList >(
*this, evt, eventType );
}
struct outer_state_ptr_impl_non_outermost
{
template< class State >
static const state_base_type * outer_state_ptr_impl( const State & stt )
{
return get_pointer( stt.pContext_ );
}
};
friend struct outer_state_ptr_impl_non_outermost;
struct outer_state_ptr_impl_outermost
{
template< class State >
static const state_base_type * outer_state_ptr_impl( const State & )
{
return 0;
}
};
struct deep_construct_inner_impl_non_empty
{
template< class InnerList >
static void deep_construct_inner_impl(
const inner_context_ptr_type & pInnerContext,
outermost_context_base_type & outermostContextBase )
{
typedef typename mpl::front< InnerList >::type current_inner;
// If you receive a
// "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
// similar compiler error here then there is a mismatch between the
// orthogonal position of a state and its position in the inner
// initial list of its outer state.
BOOST_STATIC_ASSERT( ( is_same<
current_inner,
typename mpl::at<
typename current_inner::context_type::inner_initial_list,
typename current_inner::orthogonal_position >::type >::value ) );
current_inner::deep_construct( pInnerContext, outermostContextBase );
deep_construct_inner< typename mpl::pop_front< InnerList >::type >(
pInnerContext, outermostContextBase );
}
};
struct deep_construct_inner_impl_empty
{
template< class InnerList >
static void deep_construct_inner_impl(
const inner_context_ptr_type &, outermost_context_base_type & ) {}
};
struct check_store_shallow_history_impl_no
{
template< class State >
static void check_store_shallow_history_impl( State & ) {}
};
struct check_store_shallow_history_impl_yes
{
template< class State >
static void check_store_shallow_history_impl( State & stt )
{
stt.outermost_context_base().template store_shallow_history<
MostDerived >();
}
};
friend struct check_store_shallow_history_impl_yes;
template< class StoreShallowHistory >
void check_store_shallow_history()
{
typedef typename mpl::if_<
StoreShallowHistory,
check_store_shallow_history_impl_yes,
check_store_shallow_history_impl_no
>::type impl;
impl::check_store_shallow_history_impl( *this );
}
struct check_store_deep_history_impl_no
{
template< class State >
static void check_store_deep_history_impl( State & ) {}
};
struct check_store_deep_history_impl_yes
{
template< class State >
static void check_store_deep_history_impl( State & stt )
{
stt.template store_deep_history_impl< MostDerived >();
}
};
friend struct check_store_deep_history_impl_yes;
template< class StoreDeepHistory >
void check_store_deep_history()
{
typedef typename mpl::if_<
StoreDeepHistory,
check_store_deep_history_impl_yes,
check_store_deep_history_impl_no
>::type impl;
impl::check_store_deep_history_impl( *this );
}
context_ptr_type pContext_;
};
#ifdef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace statechart
#endif
template< class MostDerived, class Context,
class InnerInitial, history_mode historyMode >
inline void intrusive_ptr_release( const ::boost::statechart::simple_state<
MostDerived, Context, InnerInitial, historyMode > * pBase )
{
if ( pBase->release() )
{
// The cast is necessary because the simple_state destructor is non-
// virtual (and inaccessible from this context)
delete polymorphic_downcast< const MostDerived * >( pBase );
}
}
#ifndef BOOST_NO_ARGUMENT_DEPENDENT_LOOKUP
} // namespace statechart
#endif
} // namespace boost
#endif

102
test/external/boost/statechart/state.hpp vendored Normal file
View File

@@ -0,0 +1,102 @@
#ifndef BOOST_STATECHART_STATE_HPP_INCLUDED
#define BOOST_STATECHART_STATE_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/simple_state.hpp>
#include <boost/mpl/list.hpp>
namespace boost
{
namespace statechart
{
template< class MostDerived,
class Context,
class InnerInitial = mpl::list<>,
history_mode historyMode = has_no_history >
class state : public simple_state<
MostDerived, Context, InnerInitial, historyMode >
{
typedef simple_state< MostDerived, Context, InnerInitial, historyMode >
base_type;
protected:
//////////////////////////////////////////////////////////////////////////
struct my_context
{
my_context( typename base_type::context_ptr_type pContext ) :
pContext_( pContext )
{
}
typename base_type::context_ptr_type pContext_;
};
typedef state my_base;
state( my_context ctx )
{
this->set_context( ctx.pContext_ );
}
~state() {}
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
// See base class for documentation
typedef typename base_type::outermost_context_base_type
outermost_context_base_type;
typedef typename base_type::inner_context_ptr_type inner_context_ptr_type;
typedef typename base_type::context_ptr_type context_ptr_type;
typedef typename base_type::inner_initial_list inner_initial_list;
static void initial_deep_construct(
outermost_context_base_type & outermostContextBase )
{
deep_construct( &outermostContextBase, outermostContextBase );
}
// See base class for documentation
static void deep_construct(
const context_ptr_type & pContext,
outermost_context_base_type & outermostContextBase )
{
const inner_context_ptr_type pInnerContext(
shallow_construct( pContext, outermostContextBase ) );
base_type::template deep_construct_inner< inner_initial_list >(
pInnerContext, outermostContextBase );
}
static inner_context_ptr_type shallow_construct(
const context_ptr_type & pContext,
outermost_context_base_type & outermostContextBase )
{
const inner_context_ptr_type pInnerContext(
new MostDerived( my_context( pContext ) ) );
outermostContextBase.add( pInnerContext );
return pInnerContext;
}
};
} // namespace statechart
} // namespace boost
#endif

File diff suppressed because it is too large Load Diff

View File

@@ -0,0 +1,71 @@
#ifndef BOOST_STATECHART_TERMINATION_HPP_INCLUDED
#define BOOST_STATECHART_TERMINATION_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/result.hpp>
namespace boost
{
namespace statechart
{
class event_base;
//////////////////////////////////////////////////////////////////////////////
template< class Event >
class termination
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase &, const IdType & eventType )
{
if ( eventType == Event::static_type() )
{
return detail::result_utility::get_result( stt.terminate() );
}
else
{
return detail::no_reaction;
}
}
};
template<>
class termination< event_base >
{
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase &, const IdType & )
{
return detail::result_utility::get_result( stt.terminate() );
}
};
} // namespace statechart
} // namespace boost
#endif

View File

@@ -0,0 +1,70 @@
#ifndef BOOST_STATECHART_TRANSITION_HPP_INCLUDED
#define BOOST_STATECHART_TRANSITION_HPP_INCLUDED
//////////////////////////////////////////////////////////////////////////////
// Copyright 2002-2008 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/result.hpp>
#include <boost/statechart/detail/reaction_dispatcher.hpp>
namespace boost
{
namespace statechart
{
//////////////////////////////////////////////////////////////////////////////
template< class Event, class Destination,
class TransitionContext = detail::no_context< Event >,
void ( TransitionContext::*pTransitionAction )( const Event & ) =
&detail::no_context< Event >::no_function >
class transition
{
private:
//////////////////////////////////////////////////////////////////////////
template< class State >
struct reactions
{
static result react_without_action( State & stt )
{
return stt.template transit< Destination >();
}
static result react_with_action( State & stt, const Event & evt )
{
return stt.template transit< Destination >( pTransitionAction, evt );
}
};
public:
//////////////////////////////////////////////////////////////////////////
// The following declarations should be private.
// They are only public because many compilers lack template friends.
//////////////////////////////////////////////////////////////////////////
template< class State, class EventBase, class IdType >
static detail::reaction_result react(
State & stt, const EventBase & evt, const IdType & eventType )
{
typedef detail::reaction_dispatcher<
reactions< State >, State, EventBase, Event, TransitionContext, IdType
> dispatcher;
return dispatcher::react( stt, evt, eventType );
}
};
} // namespace statechart
} // namespace boost
#endif