summaryrefslogtreecommitdiff
path: root/boost/statechart
diff options
context:
space:
mode:
authorAnas Nashif <anas.nashif@intel.com>2012-10-30 19:57:26 (GMT)
committerAnas Nashif <anas.nashif@intel.com>2012-10-30 19:57:26 (GMT)
commit1a78a62555be32868418fe52f8e330c9d0f95d5a (patch)
treed3765a80e7d3b9640ec2e930743630cd6b9fce2b /boost/statechart
downloadboost-1a78a62555be32868418fe52f8e330c9d0f95d5a.zip
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.gz
boost-1a78a62555be32868418fe52f8e330c9d0f95d5a.tar.bz2
Imported Upstream version 1.49.0upstream/1.49.0
Diffstat (limited to 'boost/statechart')
-rw-r--r--boost/statechart/asynchronous_state_machine.hpp89
-rw-r--r--boost/statechart/custom_reaction.hpp74
-rw-r--r--boost/statechart/deep_history.hpp63
-rw-r--r--boost/statechart/deferral.hpp71
-rw-r--r--boost/statechart/detail/avoid_unused_warning.hpp31
-rw-r--r--boost/statechart/detail/constructor.hpp139
-rw-r--r--boost/statechart/detail/counted_base.hpp92
-rw-r--r--boost/statechart/detail/leaf_state.hpp84
-rw-r--r--boost/statechart/detail/memory.hpp72
-rw-r--r--boost/statechart/detail/node_state.hpp156
-rw-r--r--boost/statechart/detail/reaction_dispatcher.hpp121
-rw-r--r--boost/statechart/detail/rtti_policy.hpp208
-rw-r--r--boost/statechart/detail/state_base.hpp191
-rw-r--r--boost/statechart/event.hpp78
-rw-r--r--boost/statechart/event_base.hpp127
-rw-r--r--boost/statechart/event_processor.hpp87
-rw-r--r--boost/statechart/exception_translator.hpp58
-rw-r--r--boost/statechart/fifo_scheduler.hpp203
-rw-r--r--boost/statechart/fifo_worker.hpp208
-rw-r--r--boost/statechart/history.hpp16
-rw-r--r--boost/statechart/in_state_reaction.hpp73
-rw-r--r--boost/statechart/null_exception_translator.hpp44
-rw-r--r--boost/statechart/processor_container.hpp445
-rw-r--r--boost/statechart/result.hpp122
-rw-r--r--boost/statechart/shallow_history.hpp63
-rw-r--r--boost/statechart/simple_state.hpp998
-rw-r--r--boost/statechart/state.hpp102
-rw-r--r--boost/statechart/state_machine.hpp1091
-rw-r--r--boost/statechart/termination.hpp71
-rw-r--r--boost/statechart/transition.hpp70
30 files changed, 5247 insertions, 0 deletions
diff --git a/boost/statechart/asynchronous_state_machine.hpp b/boost/statechart/asynchronous_state_machine.hpp
new file mode 100644
index 0000000..4870457
--- /dev/null
+++ b/boost/statechart/asynchronous_state_machine.hpp
@@ -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
diff --git a/boost/statechart/custom_reaction.hpp b/boost/statechart/custom_reaction.hpp
new file mode 100644
index 0000000..61767a9
--- /dev/null
+++ b/boost/statechart/custom_reaction.hpp
@@ -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
diff --git a/boost/statechart/deep_history.hpp b/boost/statechart/deep_history.hpp
new file mode 100644
index 0000000..4a108d0
--- /dev/null
+++ b/boost/statechart/deep_history.hpp
@@ -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
diff --git a/boost/statechart/deferral.hpp b/boost/statechart/deferral.hpp
new file mode 100644
index 0000000..8bb6f72
--- /dev/null
+++ b/boost/statechart/deferral.hpp
@@ -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
diff --git a/boost/statechart/detail/avoid_unused_warning.hpp b/boost/statechart/detail/avoid_unused_warning.hpp
new file mode 100644
index 0000000..1c002a4
--- /dev/null
+++ b/boost/statechart/detail/avoid_unused_warning.hpp
@@ -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
diff --git a/boost/statechart/detail/constructor.hpp b/boost/statechart/detail/constructor.hpp
new file mode 100644
index 0000000..0cc317a
--- /dev/null
+++ b/boost/statechart/detail/constructor.hpp
@@ -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
diff --git a/boost/statechart/detail/counted_base.hpp b/boost/statechart/detail/counted_base.hpp
new file mode 100644
index 0000000..4266f30
--- /dev/null
+++ b/boost/statechart/detail/counted_base.hpp
@@ -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
diff --git a/boost/statechart/detail/leaf_state.hpp b/boost/statechart/detail/leaf_state.hpp
new file mode 100644
index 0000000..adbcb2f
--- /dev/null
+++ b/boost/statechart/detail/leaf_state.hpp
@@ -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
diff --git a/boost/statechart/detail/memory.hpp b/boost/statechart/detail/memory.hpp
new file mode 100644
index 0000000..69d7518
--- /dev/null
+++ b/boost/statechart/detail/memory.hpp
@@ -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
diff --git a/boost/statechart/detail/node_state.hpp b/boost/statechart/detail/node_state.hpp
new file mode 100644
index 0000000..a720832
--- /dev/null
+++ b/boost/statechart/detail/node_state.hpp
@@ -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
diff --git a/boost/statechart/detail/reaction_dispatcher.hpp b/boost/statechart/detail/reaction_dispatcher.hpp
new file mode 100644
index 0000000..5404f92
--- /dev/null
+++ b/boost/statechart/detail/reaction_dispatcher.hpp
@@ -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
diff --git a/boost/statechart/detail/rtti_policy.hpp b/boost/statechart/detail/rtti_policy.hpp
new file mode 100644
index 0000000..c3e334e
--- /dev/null
+++ b/boost/statechart/detail/rtti_policy.hpp
@@ -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
diff --git a/boost/statechart/detail/state_base.hpp b/boost/statechart/detail/state_base.hpp
new file mode 100644
index 0000000..18eda5a
--- /dev/null
+++ b/boost/statechart/detail/state_base.hpp
@@ -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
diff --git a/boost/statechart/event.hpp b/boost/statechart/event.hpp
new file mode 100644
index 0000000..2a15c22
--- /dev/null
+++ b/boost/statechart/event.hpp
@@ -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
diff --git a/boost/statechart/event_base.hpp b/boost/statechart/event_base.hpp
new file mode 100644
index 0000000..1e1711a
--- /dev/null
+++ b/boost/statechart/event_base.hpp
@@ -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
diff --git a/boost/statechart/event_processor.hpp b/boost/statechart/event_processor.hpp
new file mode 100644
index 0000000..f764a6d
--- /dev/null
+++ b/boost/statechart/event_processor.hpp
@@ -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
diff --git a/boost/statechart/exception_translator.hpp b/boost/statechart/exception_translator.hpp
new file mode 100644
index 0000000..a030468
--- /dev/null
+++ b/boost/statechart/exception_translator.hpp
@@ -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
diff --git a/boost/statechart/fifo_scheduler.hpp b/boost/statechart/fifo_scheduler.hpp
new file mode 100644
index 0000000..c645d86
--- /dev/null
+++ b/boost/statechart/fifo_scheduler.hpp
@@ -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
diff --git a/boost/statechart/fifo_worker.hpp b/boost/statechart/fifo_worker.hpp
new file mode 100644
index 0000000..5f42d37
--- /dev/null
+++ b/boost/statechart/fifo_worker.hpp
@@ -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
diff --git a/boost/statechart/history.hpp b/boost/statechart/history.hpp
new file mode 100644
index 0000000..7365c63
--- /dev/null
+++ b/boost/statechart/history.hpp
@@ -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
diff --git a/boost/statechart/in_state_reaction.hpp b/boost/statechart/in_state_reaction.hpp
new file mode 100644
index 0000000..73f5028
--- /dev/null
+++ b/boost/statechart/in_state_reaction.hpp
@@ -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
diff --git a/boost/statechart/null_exception_translator.hpp b/boost/statechart/null_exception_translator.hpp
new file mode 100644
index 0000000..f44accf
--- /dev/null
+++ b/boost/statechart/null_exception_translator.hpp
@@ -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
diff --git a/boost/statechart/processor_container.hpp b/boost/statechart/processor_container.hpp
new file mode 100644
index 0000000..797e2f8
--- /dev/null
+++ b/boost/statechart/processor_container.hpp
@@ -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
diff --git a/boost/statechart/result.hpp b/boost/statechart/result.hpp
new file mode 100644
index 0000000..6843ba3
--- /dev/null
+++ b/boost/statechart/result.hpp
@@ -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
diff --git a/boost/statechart/shallow_history.hpp b/boost/statechart/shallow_history.hpp
new file mode 100644
index 0000000..fabc423
--- /dev/null
+++ b/boost/statechart/shallow_history.hpp
@@ -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
diff --git a/boost/statechart/simple_state.hpp b/boost/statechart/simple_state.hpp
new file mode 100644
index 0000000..77330f6
--- /dev/null
+++ b/boost/statechart/simple_state.hpp
@@ -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
diff --git a/boost/statechart/state.hpp b/boost/statechart/state.hpp
new file mode 100644
index 0000000..ab9ea0a
--- /dev/null
+++ b/boost/statechart/state.hpp
@@ -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
diff --git a/boost/statechart/state_machine.hpp b/boost/statechart/state_machine.hpp
new file mode 100644
index 0000000..960cbaa
--- /dev/null
+++ b/boost/statechart/state_machine.hpp
@@ -0,0 +1,1091 @@
+#ifndef BOOST_STATECHART_STATE_MACHINE_HPP_INCLUDED
+#define BOOST_STATECHART_STATE_MACHINE_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/null_exception_translator.hpp>
+#include <boost/statechart/result.hpp>
+
+#include <boost/statechart/detail/rtti_policy.hpp>
+#include <boost/statechart/detail/state_base.hpp>
+#include <boost/statechart/detail/leaf_state.hpp>
+#include <boost/statechart/detail/node_state.hpp>
+#include <boost/statechart/detail/constructor.hpp>
+#include <boost/statechart/detail/avoid_unused_warning.hpp>
+
+#include <boost/mpl/list.hpp>
+#include <boost/mpl/clear.hpp>
+#include <boost/mpl/if.hpp>
+#include <boost/mpl/at.hpp>
+#include <boost/mpl/integral_c.hpp>
+#include <boost/mpl/minus.hpp>
+#include <boost/mpl/equal_to.hpp>
+
+#include <boost/intrusive_ptr.hpp>
+#include <boost/type_traits/is_pointer.hpp>
+#include <boost/type_traits/remove_reference.hpp>
+#include <boost/noncopyable.hpp>
+#include <boost/assert.hpp>
+#include <boost/static_assert.hpp>
+#include <boost/cast.hpp> // boost::polymorphic_downcast
+// BOOST_NO_EXCEPTIONS, BOOST_MSVC, BOOST_MSVC_STD_ITERATOR
+#include <boost/config.hpp>
+
+#include <boost/detail/allocator_utilities.hpp>
+
+#ifdef BOOST_MSVC
+# pragma warning( push )
+# pragma warning( disable: 4702 ) // unreachable code (in release mode only)
+#endif
+
+#include <map>
+
+#ifdef BOOST_MSVC
+# pragma warning( pop )
+#endif
+
+#include <memory> // std::allocator
+#include <typeinfo> // std::bad_cast
+#include <functional> // std::less
+#include <iterator>
+
+
+
+namespace boost
+{
+namespace statechart
+{
+namespace detail
+{
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+template< class StateBaseType, class EventBaseType, class IdType >
+class send_function
+{
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ send_function(
+ StateBaseType & toState,
+ const EventBaseType & evt,
+ IdType eventType
+ ) :
+ toState_( toState ), evt_( evt ), eventType_( eventType )
+ {
+ }
+
+ result operator()()
+ {
+ return detail::result_utility::make_result(
+ toState_.react_impl( evt_, eventType_ ) );
+ }
+
+ private:
+ //////////////////////////////////////////////////////////////////////////
+ // avoids C4512 (assignment operator could not be generated)
+ send_function & operator=( const send_function & );
+
+ StateBaseType & toState_;
+ const EventBaseType & evt_;
+ IdType eventType_;
+};
+
+
+//////////////////////////////////////////////////////////////////////////////
+struct state_cast_impl_pointer_target
+{
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ template< class StateBaseType >
+ static const StateBaseType * deref_if_necessary(
+ const StateBaseType * pState )
+ {
+ return pState;
+ }
+
+ template< class Target, class IdType >
+ static IdType type_id()
+ {
+ Target p = 0;
+ return type_id_impl< IdType >( p );
+ }
+
+ static bool found( const void * pFound )
+ {
+ return pFound != 0;
+ }
+
+ template< class Target >
+ static Target not_found()
+ {
+ return 0;
+ }
+
+ private:
+ //////////////////////////////////////////////////////////////////////////
+ template< class IdType, class Type >
+ static IdType type_id_impl( const Type * )
+ {
+ return Type::static_type();
+ }
+};
+
+struct state_cast_impl_reference_target
+{
+ template< class StateBaseType >
+ static const StateBaseType & deref_if_necessary(
+ const StateBaseType * pState )
+ {
+ return *pState;
+ }
+
+ template< class Target, class IdType >
+ static IdType type_id()
+ {
+ return remove_reference< Target >::type::static_type();
+ }
+
+ template< class Dummy >
+ static bool found( const Dummy & )
+ {
+ return true;
+ }
+
+ template< class Target >
+ static Target not_found()
+ {
+ throw std::bad_cast();
+ }
+};
+
+template< class Target >
+struct state_cast_impl : public mpl::if_<
+ is_pointer< Target >,
+ state_cast_impl_pointer_target,
+ state_cast_impl_reference_target
+>::type {};
+
+
+//////////////////////////////////////////////////////////////////////////////
+template< class RttiPolicy >
+class history_key
+{
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ template< class HistorizedState >
+ static history_key make_history_key()
+ {
+ return history_key(
+ HistorizedState::context_type::static_type(),
+ HistorizedState::orthogonal_position::value );
+ }
+
+ typename RttiPolicy::id_type history_context_type() const
+ {
+ return historyContextType_;
+ }
+
+ friend bool operator<(
+ const history_key & left, const history_key & right )
+ {
+ return
+ std::less< typename RttiPolicy::id_type >()(
+ left.historyContextType_, right.historyContextType_ ) ||
+ ( ( left.historyContextType_ == right.historyContextType_ ) &&
+ ( left.historizedOrthogonalRegion_ <
+ right.historizedOrthogonalRegion_ ) );
+ }
+
+ private:
+ //////////////////////////////////////////////////////////////////////////
+ history_key(
+ typename RttiPolicy::id_type historyContextType,
+ orthogonal_position_type historizedOrthogonalRegion
+ ) :
+ historyContextType_( historyContextType ),
+ historizedOrthogonalRegion_( historizedOrthogonalRegion )
+ {
+ }
+
+ // avoids C4512 (assignment operator could not be generated)
+ history_key & operator=( const history_key & );
+
+ const typename RttiPolicy::id_type historyContextType_;
+ const orthogonal_position_type historizedOrthogonalRegion_;
+};
+
+
+
+} // namespace detail
+
+
+
+//////////////////////////////////////////////////////////////////////////////
+template< class MostDerived,
+ class InitialState,
+ class Allocator = std::allocator< void >,
+ class ExceptionTranslator = null_exception_translator >
+class state_machine : noncopyable
+{
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ typedef Allocator allocator_type;
+ typedef detail::rtti_policy rtti_policy_type;
+ typedef event_base event_base_type;
+ typedef intrusive_ptr< const event_base_type > event_base_ptr_type;
+
+ void initiate()
+ {
+ terminate();
+
+ {
+ terminator guard( *this, 0 );
+ detail::result_utility::get_result( translator_(
+ initial_construct_function( *this ),
+ exception_event_handler( *this ) ) );
+ guard.dismiss();
+ }
+
+ process_queued_events();
+ }
+
+ void terminate()
+ {
+ terminator guard( *this, 0 );
+ detail::result_utility::get_result( translator_(
+ terminate_function( *this ),
+ exception_event_handler( *this ) ) );
+ guard.dismiss();
+ }
+
+ bool terminated() const
+ {
+ return pOutermostState_ == 0;
+ }
+
+ void process_event( const event_base_type & evt )
+ {
+ if ( send_event( evt ) == detail::do_defer_event )
+ {
+ deferredEventQueue_.push_back( evt.intrusive_from_this() );
+ }
+
+ process_queued_events();
+ }
+
+ template< class Target >
+ Target state_cast() const
+ {
+ typedef detail::state_cast_impl< Target > impl;
+
+ for ( typename state_list_type::const_iterator pCurrentLeafState =
+ currentStates_.begin();
+ pCurrentLeafState != currentStatesEnd_;
+ ++pCurrentLeafState )
+ {
+ const state_base_type * pCurrentState(
+ get_pointer( *pCurrentLeafState ) );
+
+ while ( pCurrentState != 0 )
+ {
+ // The unnecessary try/catch overhead for pointer targets is
+ // typically small compared to the cycles dynamic_cast needs
+ #ifndef BOOST_NO_EXCEPTIONS
+ try
+ #endif
+ {
+ Target result = dynamic_cast< Target >(
+ impl::deref_if_necessary( pCurrentState ) );
+
+ if ( impl::found( result ) )
+ {
+ return result;
+ }
+ }
+ #ifndef BOOST_NO_EXCEPTIONS
+ // Intentionally swallow std::bad_cast exceptions. We'll throw one
+ // ourselves when we fail to find a state that can be cast to Target
+ catch ( const std::bad_cast & ) {}
+ #endif
+
+ pCurrentState = pCurrentState->outer_state_ptr();
+ }
+ }
+
+ return impl::template not_found< Target >();
+ }
+
+ template< class Target >
+ Target state_downcast() const
+ {
+ typedef detail::state_cast_impl< Target > impl;
+
+ typename rtti_policy_type::id_type targetType =
+ impl::template type_id< Target, rtti_policy_type::id_type >();
+
+ for ( typename state_list_type::const_iterator pCurrentLeafState =
+ currentStates_.begin();
+ pCurrentLeafState != currentStatesEnd_;
+ ++pCurrentLeafState )
+ {
+ const state_base_type * pCurrentState(
+ get_pointer( *pCurrentLeafState ) );
+
+ while ( pCurrentState != 0 )
+ {
+ if ( pCurrentState->dynamic_type() == targetType )
+ {
+ return static_cast< Target >(
+ impl::deref_if_necessary( pCurrentState ) );
+ }
+
+ pCurrentState = pCurrentState->outer_state_ptr();
+ }
+ }
+
+ return impl::template not_found< Target >();
+ }
+
+ typedef detail::state_base< allocator_type, rtti_policy_type >
+ state_base_type;
+
+ class state_iterator : public std::iterator<
+ std::forward_iterator_tag,
+ state_base_type, std::ptrdiff_t
+ #ifndef BOOST_MSVC_STD_ITERATOR
+ , const state_base_type *, const state_base_type &
+ #endif
+ >
+ {
+ public:
+ //////////////////////////////////////////////////////////////////////
+ explicit state_iterator(
+ typename state_base_type::state_list_type::const_iterator
+ baseIterator
+ ) : baseIterator_( baseIterator ) {}
+
+ const state_base_type & operator*() const { return **baseIterator_; }
+ const state_base_type * operator->() const
+ {
+ return &**baseIterator_;
+ }
+
+ state_iterator & operator++() { ++baseIterator_; return *this; }
+ state_iterator operator++( int )
+ {
+ return state_iterator( baseIterator_++ );
+ }
+
+ bool operator==( const state_iterator & right ) const
+ {
+ return baseIterator_ == right.baseIterator_;
+ }
+ bool operator!=( const state_iterator & right ) const
+ {
+ return !( *this == right );
+ }
+
+ private:
+ typename state_base_type::state_list_type::const_iterator
+ baseIterator_;
+ };
+
+ state_iterator state_begin() const
+ {
+ return state_iterator( currentStates_.begin() );
+ }
+
+ state_iterator state_end() const
+ {
+ return state_iterator( currentStatesEnd_ );
+ }
+
+ void unconsumed_event( const event_base & ) {}
+
+ protected:
+ //////////////////////////////////////////////////////////////////////////
+ state_machine() :
+ currentStatesEnd_( currentStates_.end() ),
+ pOutermostState_( 0 ),
+ isInnermostCommonOuter_( false ),
+ performFullExit_( true ),
+ pTriggeringEvent_( 0 )
+ {
+ }
+
+ // This destructor was only made virtual so that that
+ // polymorphic_downcast can be used to cast to MostDerived.
+ virtual ~state_machine()
+ {
+ terminate_impl( false );
+ }
+
+ void post_event( const event_base_ptr_type & pEvent )
+ {
+ post_event_impl( pEvent );
+ }
+
+ void post_event( const event_base & evt )
+ {
+ post_event_impl( evt );
+ }
+
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ // The following declarations should be protected.
+ // They are only public because many compilers lack template friends.
+ //////////////////////////////////////////////////////////////////////////
+ template<
+ class HistoryContext,
+ detail::orthogonal_position_type orthogonalPosition >
+ void clear_shallow_history()
+ {
+ // If you receive a
+ // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
+ // similar compiler error here then you tried to clear shallow history
+ // for a state that does not have shallow history. That is, the state
+ // does not pass either statechart::has_shallow_history or
+ // statechart::has_full_history to its base class template.
+ BOOST_STATIC_ASSERT( HistoryContext::shallow_history::value );
+
+ typedef typename mpl::at_c<
+ typename HistoryContext::inner_initial_list,
+ orthogonalPosition >::type historized_state;
+
+ store_history_impl(
+ shallowHistoryMap_,
+ history_key_type::make_history_key< historized_state >(),
+ 0 );
+ }
+
+ template<
+ class HistoryContext,
+ detail::orthogonal_position_type orthogonalPosition >
+ void clear_deep_history()
+ {
+ // If you receive a
+ // "use of undefined type 'boost::STATIC_ASSERTION_FAILURE<x>'" or
+ // similar compiler error here then you tried to clear deep history for
+ // a state that does not have deep history. That is, the state does not
+ // pass either statechart::has_deep_history or
+ // statechart::has_full_history to its base class template
+ BOOST_STATIC_ASSERT( HistoryContext::deep_history::value );
+
+ typedef typename mpl::at_c<
+ typename HistoryContext::inner_initial_list,
+ orthogonalPosition >::type historized_state;
+
+ store_history_impl(
+ deepHistoryMap_,
+ history_key_type::make_history_key< historized_state >(),
+ 0 );
+ }
+
+ const event_base_type * triggering_event() const
+ {
+ return pTriggeringEvent_;
+ }
+
+ public:
+ //////////////////////////////////////////////////////////////////////////
+ // The following declarations should be private.
+ // They are only public because many compilers lack template friends.
+ //////////////////////////////////////////////////////////////////////////
+ typedef MostDerived inner_context_type;
+ typedef mpl::integral_c< detail::orthogonal_position_type, 0 >
+ inner_orthogonal_position;
+ typedef mpl::integral_c< detail::orthogonal_position_type, 1 >
+ no_of_orthogonal_regions;
+
+ typedef MostDerived outermost_context_type;
+ typedef state_machine outermost_context_base_type;
+ typedef state_machine * inner_context_ptr_type;
+ typedef typename state_base_type::node_state_base_ptr_type
+ node_state_base_ptr_type;
+ typedef typename state_base_type::leaf_state_ptr_type leaf_state_ptr_type;
+ typedef typename state_base_type::state_list_type state_list_type;
+
+ typedef mpl::clear< mpl::list<> >::type context_type_list;
+
+ typedef mpl::bool_< false > shallow_history;
+ typedef mpl::bool_< false > deep_history;
+ typedef mpl::bool_< false > inherited_deep_history;
+
+ void post_event_impl( const event_base_ptr_type & pEvent )
+ {
+ BOOST_ASSERT( get_pointer( pEvent ) != 0 );
+ eventQueue_.push_back( pEvent );
+ }
+
+ void post_event_impl( const event_base & evt )
+ {
+ post_event_impl( evt.intrusive_from_this() );
+ }
+
+ detail::reaction_result react_impl(
+ const event_base_type &,
+ typename rtti_policy_type::id_type )
+ {
+ return detail::do_forward_event;
+ }
+
+ void exit_impl(
+ inner_context_ptr_type &,
+ typename state_base_type::node_state_base_ptr_type &,
+ bool ) {}
+
+ void set_outermost_unstable_state(
+ typename state_base_type::node_state_base_ptr_type &
+ pOutermostUnstableState )
+ {
+ pOutermostUnstableState = 0;
+ }
+
+ // Returns a reference to the context identified by the template
+ // parameter. This can either be _this_ object or one of its direct or
+ // indirect contexts.
+ template< class Context >
+ Context & context()
+ {
+ // As we are in the outermost context here, only this object can be
+ // returned.
+ return *polymorphic_downcast< MostDerived * >( this );
+ }
+
+ template< class Context >
+ const Context & context() const
+ {
+ // As we are in the outermost context here, only this object can be
+ // returned.
+ return *polymorphic_downcast< const MostDerived * >( this );
+ }
+
+ outermost_context_type & outermost_context()
+ {
+ return *polymorphic_downcast< MostDerived * >( this );
+ }
+
+ const outermost_context_type & outermost_context() const
+ {
+ return *polymorphic_downcast< const MostDerived * >( this );
+ }
+
+ outermost_context_base_type & outermost_context_base()
+ {
+ return *this;
+ }
+
+ const outermost_context_base_type & outermost_context_base() const
+ {
+ return *this;
+ }
+
+ void terminate_as_reaction( state_base_type & theState )
+ {
+ terminate_impl( theState, performFullExit_ );
+ pOutermostUnstableState_ = 0;
+ }
+
+ void terminate_as_part_of_transit( state_base_type & theState )
+ {
+ terminate_impl( theState, performFullExit_ );
+ isInnermostCommonOuter_ = true;
+ }
+
+ void terminate_as_part_of_transit( state_machine & )
+ {
+ terminate_impl( *pOutermostState_, performFullExit_ );
+ isInnermostCommonOuter_ = true;
+ }
+
+
+ template< class State >
+ void add( const intrusive_ptr< State > & pState )
+ {
+ // The second dummy argument is necessary because the call to the
+ // overloaded function add_impl would otherwise be ambiguous.
+ node_state_base_ptr_type pNewOutermostUnstableStateCandidate =
+ add_impl( pState, *pState );
+
+ if ( isInnermostCommonOuter_ ||
+ ( is_in_highest_orthogonal_region< State >() &&
+ ( get_pointer( pOutermostUnstableState_ ) ==
+ pState->State::outer_state_ptr() ) ) )
+ {
+ isInnermostCommonOuter_ = false;
+ pOutermostUnstableState_ = pNewOutermostUnstableStateCandidate;
+ }
+ }
+
+
+ void add_inner_state(
+ detail::orthogonal_position_type position,
+ state_base_type * pOutermostState )
+ {
+ BOOST_ASSERT( position == 0 );
+ detail::avoid_unused_warning( position );
+ pOutermostState_ = pOutermostState;
+ }
+
+ void remove_inner_state( detail::orthogonal_position_type position )
+ {
+ BOOST_ASSERT( position == 0 );
+ detail::avoid_unused_warning( position );
+ pOutermostState_ = 0;
+ }
+
+
+ void release_events()
+ {
+ eventQueue_.splice( eventQueue_.begin(), deferredEventQueue_ );
+ }
+
+
+ template< class HistorizedState >
+ void store_shallow_history()
+ {
+ // 5.2.10.6 declares that reinterpret_casting a function pointer to a
+ // different function pointer and back must yield the same value. The
+ // following reinterpret_cast is the first half of such a sequence.
+ store_history_impl(
+ shallowHistoryMap_,
+ history_key_type::make_history_key< HistorizedState >(),
+ reinterpret_cast< void (*)() >( &HistorizedState::deep_construct ) );
+ }
+
+ template< class DefaultState >
+ void construct_with_shallow_history(
+ const typename DefaultState::context_ptr_type & pContext )
+ {
+ construct_with_history_impl< DefaultState >(
+ shallowHistoryMap_, pContext );
+ }
+
+
+ template< class HistorizedState, class LeafState >
+ void store_deep_history()
+ {
+ typedef typename detail::make_context_list<
+ typename HistorizedState::context_type,
+ LeafState >::type history_context_list;
+ typedef detail::constructor<
+ history_context_list, outermost_context_base_type > constructor_type;
+ // 5.2.10.6 declares that reinterpret_casting a function pointer to a
+ // different function pointer and back must yield the same value. The
+ // following reinterpret_cast is the first half of such a sequence.
+ store_history_impl(
+ deepHistoryMap_,
+ history_key_type::make_history_key< HistorizedState >(),
+ reinterpret_cast< void (*)() >( &constructor_type::construct ) );
+ }
+
+ template< class DefaultState >
+ void construct_with_deep_history(
+ const typename DefaultState::context_ptr_type & pContext )
+ {
+ construct_with_history_impl< DefaultState >(
+ deepHistoryMap_, pContext );
+ }
+
+ private: // implementation
+ //////////////////////////////////////////////////////////////////////////
+ void initial_construct()
+ {
+ InitialState::initial_deep_construct(
+ *polymorphic_downcast< MostDerived * >( this ) );
+ }
+
+ class initial_construct_function
+ {
+ public:
+ //////////////////////////////////////////////////////////////////////
+ initial_construct_function( state_machine & machine ) :
+ machine_( machine )
+ {
+ }
+
+ result operator()()
+ {
+ machine_.initial_construct();
+ return detail::result_utility::make_result(
+ detail::do_discard_event ); // there is nothing to be consumed
+ }
+
+ private:
+ //////////////////////////////////////////////////////////////////////
+ // avoids C4512 (assignment operator could not be generated)
+ initial_construct_function & operator=(
+ const initial_construct_function & );
+
+ state_machine & machine_;
+ };
+ friend class initial_construct_function;
+
+ class terminate_function
+ {
+ public:
+ //////////////////////////////////////////////////////////////////////
+ terminate_function( state_machine & machine ) : machine_( machine ) {}
+
+ result operator()()
+ {
+ machine_.terminate_impl( true );
+ return detail::result_utility::make_result(
+ detail::do_discard_event ); // there is nothing to be consumed
+ }
+
+ private:
+ //////////////////////////////////////////////////////////////////////
+ // avoids C4512 (assignment operator could not be generated)
+ terminate_function & operator=( const terminate_function & );
+
+ state_machine & machine_;
+ };
+ friend class terminate_function;
+
+ template< class ExceptionEvent >
+ detail::reaction_result handle_exception_event(
+ const ExceptionEvent & exceptionEvent,
+ state_base_type * pCurrentState )
+ {
+ if ( terminated() )
+ {
+ // there is no state that could handle the exception -> bail out
+ throw;
+ }
+
+ // If we are stable, an event handler has thrown.
+ // Otherwise, either a state constructor, a transition action or an exit
+ // function has thrown and the state machine is now in an invalid state.
+ // This situation can be resolved by the exception event handler
+ // function by orderly transiting to another state or terminating.
+ // As a result of this, the machine must not be unstable when this
+ // function is left.
+ state_base_type * const pOutermostUnstableState =
+ get_pointer( pOutermostUnstableState_ );
+ state_base_type * const pHandlingState = pOutermostUnstableState == 0 ?
+ pCurrentState : pOutermostUnstableState;
+
+ BOOST_ASSERT( pHandlingState != 0 );
+ terminator guard( *this, &exceptionEvent );
+ // There is another scope guard up the call stack, which will terminate
+ // the machine. So this guard only sets the triggering event.
+ guard.dismiss();
+
+ // Setting a member variable to a special value for the duration of a
+ // call surely looks like a kludge (normally it should be a parameter of
+ // the call). However, in this case it is unavoidable because the call
+ // below could result in a call to user code where passing through an
+ // additional bool parameter is not acceptable.
+ performFullExit_ = false;
+ const detail::reaction_result reactionResult = pHandlingState->react_impl(
+ exceptionEvent, exceptionEvent.dynamic_type() );
+ // If the above call throws then performFullExit_ will obviously not be
+ // set back to true. In this case the termination triggered by the
+ // scope guard further up in the call stack will take care of this.
+ performFullExit_ = true;
+
+ if ( ( reactionResult != detail::do_discard_event ) ||
+ ( get_pointer( pOutermostUnstableState_ ) != 0 ) )
+ {
+ throw;
+ }
+
+ return detail::do_discard_event;
+ }
+
+ class exception_event_handler
+ {
+ public:
+ //////////////////////////////////////////////////////////////////////
+ exception_event_handler(
+ state_machine & machine,
+ state_base_type * pCurrentState = 0
+ ) :
+ machine_( machine ),
+ pCurrentState_( pCurrentState )
+ {
+ }
+
+ template< class ExceptionEvent >
+ result operator()(
+ const ExceptionEvent & exceptionEvent )
+ {
+ return detail::result_utility::make_result(
+ machine_.handle_exception_event(
+ exceptionEvent, pCurrentState_ ) );
+ }
+
+ private:
+ //////////////////////////////////////////////////////////////////////
+ // avoids C4512 (assignment operator could not be generated)
+ exception_event_handler & operator=(
+ const exception_event_handler & );
+
+ state_machine & machine_;
+ state_base_type * pCurrentState_;
+ };
+ friend class exception_event_handler;
+
+ class terminator
+ {
+ public:
+ //////////////////////////////////////////////////////////////////////
+ terminator(
+ state_machine & machine, const event_base * pNewTriggeringEvent ) :
+ machine_( machine ),
+ pOldTriggeringEvent_(machine_.pTriggeringEvent_),
+ dismissed_( false )
+ {
+ machine_.pTriggeringEvent_ = pNewTriggeringEvent;
+ }
+
+ ~terminator()
+ {
+ if ( !dismissed_ ) { machine_.terminate_impl( false ); }
+ machine_.pTriggeringEvent_ = pOldTriggeringEvent_;
+ }
+
+ void dismiss() { dismissed_ = true; }
+
+ private:
+ //////////////////////////////////////////////////////////////////////
+ // avoids C4512 (assignment operator could not be generated)
+ terminator & operator=( const terminator & );
+
+ state_machine & machine_;
+ const event_base_type * const pOldTriggeringEvent_;
+ bool dismissed_;
+ };
+ friend class terminator;
+
+
+ detail::reaction_result send_event( const event_base_type & evt )
+ {
+ terminator guard( *this, &evt );
+ BOOST_ASSERT( get_pointer( pOutermostUnstableState_ ) == 0 );
+ const typename rtti_policy_type::id_type eventType = evt.dynamic_type();
+ detail::reaction_result reactionResult = detail::do_forward_event;
+
+ for (
+ typename state_list_type::iterator pState = currentStates_.begin();
+ ( reactionResult == detail::do_forward_event ) &&
+ ( pState != currentStatesEnd_ );
+ ++pState )
+ {
+ // CAUTION: The following statement could modify our state list!
+ // We must not continue iterating if the event was consumed
+ reactionResult = detail::result_utility::get_result( translator_(
+ detail::send_function<
+ state_base_type, event_base_type, rtti_policy_type::id_type >(
+ **pState, evt, eventType ),
+ exception_event_handler( *this, get_pointer( *pState ) ) ) );
+ }
+
+ guard.dismiss();
+
+ if ( reactionResult == detail::do_forward_event )
+ {
+ polymorphic_downcast< MostDerived * >( this )->unconsumed_event( evt );
+ }
+
+ return reactionResult;
+ }
+
+
+ void process_queued_events()
+ {
+ while ( !eventQueue_.empty() )
+ {
+ event_base_ptr_type pEvent = eventQueue_.front();
+ eventQueue_.pop_front();
+
+ if ( send_event( *pEvent ) == detail::do_defer_event )
+ {
+ deferredEventQueue_.push_back( pEvent );
+ }
+ }
+ }
+
+
+ void terminate_impl( bool performFullExit )
+ {
+ performFullExit_ = true;
+
+ if ( !terminated() )
+ {
+ terminate_impl( *pOutermostState_, performFullExit );
+ }
+
+ eventQueue_.clear();
+ deferredEventQueue_.clear();
+ shallowHistoryMap_.clear();
+ deepHistoryMap_.clear();
+ }
+
+ void terminate_impl( state_base_type & theState, bool performFullExit )
+ {
+ isInnermostCommonOuter_ = false;
+
+ // If pOutermostUnstableState_ == 0, we know for sure that
+ // currentStates_.size() > 0, otherwise theState couldn't be alive any
+ // more
+ if ( get_pointer( pOutermostUnstableState_ ) != 0 )
+ {
+ theState.remove_from_state_list(
+ currentStatesEnd_, pOutermostUnstableState_, performFullExit );
+ }
+ // Optimization: We want to find out whether currentStates_ has size 1
+ // and if yes use the optimized implementation below. Since
+ // list<>::size() is implemented quite inefficiently in some std libs
+ // it is best to just decrement the currentStatesEnd_ here and
+ // increment it again, if the test failed.
+ else if ( currentStates_.begin() == --currentStatesEnd_ )
+ {
+ // The machine is stable and there is exactly one innermost state.
+ // The following optimization is only correct for a stable machine
+ // without orthogonal regions.
+ leaf_state_ptr_type & pState = *currentStatesEnd_;
+ pState->exit_impl(
+ pState, pOutermostUnstableState_, performFullExit );
+ }
+ else
+ {
+ BOOST_ASSERT( currentStates_.size() > 1 );
+ // The machine is stable and there are multiple innermost states
+ theState.remove_from_state_list(
+ ++currentStatesEnd_, pOutermostUnstableState_, performFullExit );
+ }
+ }
+
+
+ node_state_base_ptr_type add_impl(
+ const leaf_state_ptr_type & pState,
+ detail::leaf_state< allocator_type, rtti_policy_type > & )
+ {
+ if ( currentStatesEnd_ == currentStates_.end() )
+ {
+ pState->set_list_position(
+ currentStates_.insert( currentStatesEnd_, pState ) );
+ }
+ else
+ {
+ *currentStatesEnd_ = pState;
+ pState->set_list_position( currentStatesEnd_ );
+ ++currentStatesEnd_;
+ }
+
+ return 0;
+ }
+
+ node_state_base_ptr_type add_impl(
+ const node_state_base_ptr_type & pState,
+ state_base_type & )
+ {
+ return pState;
+ }
+
+ template< class State >
+ static bool is_in_highest_orthogonal_region()
+ {
+ return mpl::equal_to<
+ typename State::orthogonal_position,
+ mpl::minus<
+ typename State::context_type::no_of_orthogonal_regions,
+ mpl::integral_c< detail::orthogonal_position_type, 1 > >
+ >::value;
+ }
+
+
+ typedef detail::history_key< rtti_policy_type > history_key_type;
+
+ typedef std::map<
+ history_key_type, void (*)(),
+ std::less< history_key_type >,
+ typename boost::detail::allocator::rebind_to<
+ allocator_type, std::pair< const history_key_type, void (*)() >
+ >::type
+ > history_map_type;
+
+ void store_history_impl(
+ history_map_type & historyMap,
+ const history_key_type & historyId,
+ void (*pConstructFunction)() )
+ {
+ historyMap[ historyId ] = pConstructFunction;
+ }
+
+ template< class DefaultState >
+ void construct_with_history_impl(
+ history_map_type & historyMap,
+ const typename DefaultState::context_ptr_type & pContext )
+ {
+ typename history_map_type::iterator pFoundSlot = historyMap.find(
+ history_key_type::make_history_key< DefaultState >() );
+
+ if ( ( pFoundSlot == historyMap.end() ) || ( pFoundSlot->second == 0 ) )
+ {
+ // We have never entered this state before or history was cleared
+ DefaultState::deep_construct(
+ pContext, *polymorphic_downcast< MostDerived * >( this ) );
+ }
+ else
+ {
+ typedef void construct_function(
+ const typename DefaultState::context_ptr_type &,
+ typename DefaultState::outermost_context_base_type & );
+ // 5.2.10.6 declares that reinterpret_casting a function pointer to a
+ // different function pointer and back must yield the same value. The
+ // following reinterpret_cast is the second half of such a sequence.
+ construct_function * const pConstructFunction =
+ reinterpret_cast< construct_function * >( pFoundSlot->second );
+ (*pConstructFunction)(
+ pContext, *polymorphic_downcast< MostDerived * >( this ) );
+ }
+ }
+
+ typedef std::list<
+ event_base_ptr_type,
+ typename boost::detail::allocator::rebind_to<
+ allocator_type, event_base_ptr_type >::type
+ > event_queue_type;
+
+ typedef std::map<
+ const state_base_type *, event_queue_type,
+ std::less< const state_base_type * >,
+ typename boost::detail::allocator::rebind_to<
+ allocator_type,
+ std::pair< const state_base_type * const, event_queue_type >
+ >::type
+ > deferred_map_type;
+
+
+ event_queue_type eventQueue_;
+ event_queue_type deferredEventQueue_;
+ state_list_type currentStates_;
+ typename state_list_type::iterator currentStatesEnd_;
+ state_base_type * pOutermostState_;
+ bool isInnermostCommonOuter_;
+ node_state_base_ptr_type pOutermostUnstableState_;
+ ExceptionTranslator translator_;
+ bool performFullExit_;
+ history_map_type shallowHistoryMap_;
+ history_map_type deepHistoryMap_;
+ const event_base_type * pTriggeringEvent_;
+};
+
+
+
+} // namespace statechart
+} // namespace boost
+
+
+
+#endif
diff --git a/boost/statechart/termination.hpp b/boost/statechart/termination.hpp
new file mode 100644
index 0000000..f740e92
--- /dev/null
+++ b/boost/statechart/termination.hpp
@@ -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
diff --git a/boost/statechart/transition.hpp b/boost/statechart/transition.hpp
new file mode 100644
index 0000000..76337ed
--- /dev/null
+++ b/boost/statechart/transition.hpp
@@ -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