123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156 |
- #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
|