blob: 6137f2b1289a994cb21a9c1927245ca27e0ecb92 [file] [log] [blame]
#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