|
Boost-Commit : |
Subject: [Boost-commit] svn:boost r66592 - in trunk/boost/msm: back front/euml
From: christophe.j.henry_at_[hidden]
Date: 2010-11-15 16:04:54
Author: chenry
Date: 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
New Revision: 66592
URL: http://svn.boost.org/trac/boost/changeset/66592
Log:
- added mpl_graph-based features (for entry states and checking of region orthogonality)
- added Boost.Parameter interface for back-end definition
Added:
trunk/boost/msm/back/mpl_graph_fsm_check.hpp (contents, props changed)
trunk/boost/msm/back/no_fsm_check.hpp (contents, props changed)
Text files modified:
trunk/boost/msm/back/default_compile_policy.hpp | 1
trunk/boost/msm/back/favor_compile_time.hpp | 1
trunk/boost/msm/back/history_policies.hpp | 3
trunk/boost/msm/back/metafunctions.hpp | 143 +++++++++++++++++++++++++++++++++++++++
trunk/boost/msm/back/state_machine.hpp | 113 ++++++++++++++++++++++++++----
trunk/boost/msm/front/euml/state_grammar.hpp | 1
6 files changed, 244 insertions(+), 18 deletions(-)
Modified: trunk/boost/msm/back/default_compile_policy.hpp
==============================================================================
--- trunk/boost/msm/back/default_compile_policy.hpp (original)
+++ trunk/boost/msm/back/default_compile_policy.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -17,6 +17,7 @@
{
struct favor_runtime_speed
{
+ typedef int compile_policy;
typedef ::boost::mpl::true_ add_forwarding_rows;
};
Modified: trunk/boost/msm/back/favor_compile_time.hpp
==============================================================================
--- trunk/boost/msm/back/favor_compile_time.hpp (original)
+++ trunk/boost/msm/back/favor_compile_time.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -63,6 +63,7 @@
struct favor_compile_time
{
+ typedef int compile_policy;
typedef ::boost::mpl::false_ add_forwarding_rows;
};
Modified: trunk/boost/msm/back/history_policies.hpp
==============================================================================
--- trunk/boost/msm/back/history_policies.hpp (original)
+++ trunk/boost/msm/back/history_policies.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -152,6 +152,7 @@
struct NoHistory
{
+ typedef int history_policy;
template <int NumberOfRegions>
struct apply
{
@@ -160,6 +161,7 @@
};
struct AlwaysHistory
{
+ typedef int history_policy;
template <int NumberOfRegions>
struct apply
{
@@ -169,6 +171,7 @@
template <class Events>
struct ShallowHistory
{
+ typedef int history_policy;
template <int NumberOfRegions>
struct apply
{
Modified: trunk/boost/msm/back/metafunctions.hpp
==============================================================================
--- trunk/boost/msm/back/metafunctions.hpp (original)
+++ trunk/boost/msm/back/metafunctions.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -38,10 +38,15 @@
#include <boost/mpl/insert_range.hpp>
#include <boost/mpl/front.hpp>
#include <boost/mpl/logical.hpp>
+#include <boost/mpl/plus.hpp>
#include <boost/type_traits/is_same.hpp>
#include <boost/utility/enable_if.hpp>
+// mpl_graph graph implementation and depth first search
+#include <boost/msm/mpl_graph/incidence_list_graph.hpp>
+#include <boost/msm/mpl_graph/depth_first_search.hpp>
+
BOOST_MPL_HAS_XXX_TRAIT_DEF(explicit_creation)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(pseudo_exit)
@@ -168,6 +173,7 @@
};
// builds a mpl::vector of initial states
+//TODO remove duplicate from get_initial_states
template <class region>
struct get_regions_as_sequence
{
@@ -374,7 +380,7 @@
::boost::mpl::if_<
::boost::mpl::has_key<states, ::boost::mpl::placeholders::_2>,
::boost::mpl::placeholders::_1,
- ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end<mpl::placeholders::_1>,
+ ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::end< ::boost::mpl::placeholders::_1>,
not_a_row< get_wrapped_state< ::boost::mpl::placeholders::_2> > >
>
>::type with_init;
@@ -629,6 +635,141 @@
{
typedef typename StateType::initial_event type;
};
+
+template <class TransitionTable, class InitState>
+struct build_one_orthogonal_region
+{
+ template<typename Row>
+ struct row_to_incidence :
+ ::boost::mpl::vector<
+ ::boost::mpl::pair<
+ typename Row::next_state_type,
+ typename Row::transition_event>,
+ typename Row::current_state_type,
+ typename Row::next_state_type
+ > {};
+ template<typename Row>
+ struct row_to_incidence2 :
+ ::boost::mpl::vector<
+ ::boost::mpl::pair<
+ typename Row::transition_event,
+ typename Row::next_state_type>,
+ typename Row::next_state_type,
+ typename Row::current_state_type
+ > {};
+
+ template <class Seq, class Elt>
+ struct transition_incidence_list_helper
+ {
+ typedef typename ::boost::mpl::push_back< Seq, row_to_incidence< Elt > >::type one_direction;
+ typedef typename ::boost::mpl::push_back< one_direction, row_to_incidence2< Elt > >::type type;
+ };
+
+ typedef typename ::boost::mpl::fold<
+ TransitionTable,
+ ::boost::mpl::vector<>,
+ transition_incidence_list_helper< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2>
+ >::type transition_incidence_list;
+
+ typedef ::boost::metagraph::mpl_graph::incidence_list_graph<transition_incidence_list>
+ transition_graph;
+
+ struct preordering_dfs_visitor :
+ ::boost::metagraph::mpl_graph::dfs_default_visitor_operations
+ {
+ template<typename Node, typename Graph, typename State>
+ struct discover_vertex :
+ ::boost::mpl::insert<State, Node>
+ {};
+ };
+
+ typedef typename mpl::first<
+ typename ::boost::metagraph::mpl_graph::depth_first_search<
+ transition_graph,
+ preordering_dfs_visitor,
+ ::boost::mpl::set<>,
+ InitState
+ >::type
+ >::type type;
+};
+
+// build a vector of regions states (as a set)
+// one set of states for every region
+// version if initial_state is a not sequence
+template <class TransitionTable, class InitStates,class Enable=void>
+struct build_orthogonal_regions
+{
+ typedef ::boost::mpl::set<typename build_one_orthogonal_region<TransitionTable,InitStates>::type> type;
+};
+
+// version if initial_state is a sequence
+template <class TransitionTable, class InitStates>
+struct build_orthogonal_regions
+ <TransitionTable,InitStates,
+ typename ::boost::enable_if<
+ ::boost::mpl::is_sequence<typename InitStates> >::type >
+{
+ typedef typename
+ ::boost::mpl::fold<
+ InitStates, ::boost::mpl::vector<>,
+ ::boost::mpl::push_back<
+ ::boost::mpl::placeholders::_1,
+ build_one_orthogonal_region< TransitionTable, ::boost::mpl::placeholders::_2 > >
+ >::type type;
+};
+
+template <class GraphAsSeqOfSets, class StateType>
+struct find_region_index
+{
+ typedef typename
+ ::boost::mpl::fold<
+ GraphAsSeqOfSets, ::boost::mpl::pair< ::boost::mpl::int_< -1 > /*res*/, ::boost::mpl::int_<0> /*counter*/ >,
+ ::boost::mpl::if_<
+ ::boost::mpl::has_key< ::boost::mpl::placeholders::_2, StateType >,
+ ::boost::mpl::pair<
+ ::boost::mpl::second< ::boost::mpl::placeholders::_1 >,
+ ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
+ >,
+ ::boost::mpl::pair<
+ ::boost::mpl::first< ::boost::mpl::placeholders::_1 >,
+ ::boost::mpl::next< ::boost::mpl::second< ::boost::mpl::placeholders::_1 > >
+ >
+ >
+ >::type result_pair;
+ typedef typename ::boost::mpl::first<result_pair>::type type;
+ enum {value = type::value};
+};
+
+template <typename Sequence, typename Range>
+struct set_insert_range
+{
+ typedef typename ::boost::mpl::fold<
+ Range,Sequence,
+ ::boost::mpl::insert< ::boost::mpl::placeholders::_1, ::boost::mpl::placeholders::_2 >
+ >::type type;
+};
+
+template <class Fsm>
+struct check_regions_orthogonality
+{
+ typedef typename build_orthogonal_regions<typename Fsm::stt,typename Fsm::initial_states>::type regions;
+
+ typedef typename ::boost::mpl::fold<
+ regions, ::boost::mpl::int_<0>,
+ ::boost::mpl::plus< ::boost::mpl::placeholders::_1 , ::boost::mpl::size< ::boost::mpl::placeholders::_2> >
+ >::type number_of_states_in_regions;
+
+ typedef typename ::boost::mpl::fold<
+ regions,mpl::set0<>,
+ set_insert_range<
+ ::boost::mpl::placeholders::_1,
+ ::boost::mpl::placeholders::_2 >
+ >::type one_big_states_set;
+
+ enum {states_in_regions_raw = number_of_states_in_regions::value};
+ enum {cumulated_states_in_regions_raw = ::boost::mpl::size<one_big_states_set>::value};
+};
+
// helper to find out if a SM has an active exit state and is therefore waiting for exiting
template <class StateType,class OwnerFct,class FSM>
inline
Added: trunk/boost/msm/back/mpl_graph_fsm_check.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/msm/back/mpl_graph_fsm_check.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -0,0 +1,38 @@
+// Copyright 2008 Christophe Henry
+// henry UNDERSCORE christophe AT hotmail DOT com
+// This is an extended version of the state machine available in the boost::mpl library
+// Distributed under the same license as the original.
+// Copyright for the original version:
+// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
+// under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MSM_BACK_MPL_GRAPH_FSM_CHECK_H
+#define BOOST_MSM_BACK_MPL_GRAPH_FSM_CHECK_H
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/msm/back/metafunctions.hpp>
+
+namespace boost { namespace msm { namespace back
+{
+ struct mpl_graph_fsm_check
+ {
+ typedef int fsm_check;
+ // checks that regions are truly orthogonal (one state belongs to 1 region)
+ // using the mpl_graph library (part of metagraph)
+ template <class Fsm>
+ static void check_orthogonality()
+ {
+ BOOST_MPL_ASSERT_RELATION( ::boost::msm::back::check_regions_orthogonality<Fsm>::states_in_regions_raw,
+ ==,
+ ::boost::msm::back::check_regions_orthogonality<Fsm>::cumulated_states_in_regions_raw );
+
+ }
+ };
+
+} } }//boost::msm::back
+
+
+#endif //BOOST_MSM_BACK_MPL_GRAPH_FSM_CHECK_H
Added: trunk/boost/msm/back/no_fsm_check.hpp
==============================================================================
--- (empty file)
+++ trunk/boost/msm/back/no_fsm_check.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -0,0 +1,33 @@
+// Copyright 2008 Christophe Henry
+// henry UNDERSCORE christophe AT hotmail DOT com
+// This is an extended version of the state machine available in the boost::mpl library
+// Distributed under the same license as the original.
+// Copyright for the original version:
+// Copyright 2005 David Abrahams and Aleksey Gurtovoy. Distributed
+// under the Boost Software License, Version 1.0. (See accompanying
+// file LICENSE_1_0.txt or copy at
+// http://www.boost.org/LICENSE_1_0.txt)
+
+#ifndef BOOST_MSM_BACK_NO_FSM_CHECK_H
+#define BOOST_MSM_BACK_NO_FSM_CHECK_H
+
+#include <boost/mpl/assert.hpp>
+
+#include <boost/msm/back/metafunctions.hpp>
+
+namespace boost { namespace msm { namespace back
+{
+ struct no_fsm_check
+ {
+ typedef int fsm_check;
+ // no fsm structure checking
+ template <class Fsm>
+ static void check_orthogonality()
+ {
+ }
+ };
+
+} } }//boost::msm::back
+
+
+#endif //BOOST_MSM_BACK_NO_FSM_CHECK_H
Modified: trunk/boost/msm/back/state_machine.hpp
==============================================================================
--- trunk/boost/msm/back/state_machine.hpp (original)
+++ trunk/boost/msm/back/state_machine.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -22,6 +22,7 @@
#include <boost/mpl/contains.hpp>
#include <boost/mpl/deref.hpp>
+#include <boost/mpl/assert.hpp>
#include <boost/fusion/container/vector/convert.hpp>
#include <boost/fusion/include/as_vector.hpp>
@@ -50,6 +51,8 @@
#include <boost/serialization/base_object.hpp>
+#include <boost/parameter.hpp>
+
#include <boost/msm/row_tags.hpp>
#include <boost/msm/back/fold_to_list.hpp>
#include <boost/msm/back/metafunctions.hpp>
@@ -59,6 +62,7 @@
#include <boost/msm/back/args.hpp>
#include <boost/msm/back/default_compile_policy.hpp>
#include <boost/msm/back/dispatch_table.hpp>
+#include <boost/msm/back/no_fsm_check.hpp>
BOOST_MPL_HAS_XXX_TRAIT_DEF(accept_sig)
BOOST_MPL_HAS_XXX_TRAIT_DEF(no_automatic_create)
@@ -66,6 +70,9 @@
BOOST_MPL_HAS_XXX_TRAIT_DEF(direct_entry)
BOOST_MPL_HAS_XXX_TRAIT_DEF(initial_event)
BOOST_MPL_HAS_XXX_TRAIT_DEF(do_serialize)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(history_policy)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(fsm_check)
+BOOST_MPL_HAS_XXX_TRAIT_DEF(compile_policy)
#ifndef BOOST_MSM_CONSTRUCTOR_ARG_SIZE
#define BOOST_MSM_CONSTRUCTOR_ARG_SIZE 5 // default max number of arguments for constructors
@@ -89,15 +96,64 @@
const boost::msm::back::dispatch_table<Fsm,Stt, Event,CompilePolicy>
dispatch_table<Fsm,Stt, Event,CompilePolicy>::instance;
+BOOST_PARAMETER_TEMPLATE_KEYWORD(front_end)
+BOOST_PARAMETER_TEMPLATE_KEYWORD(history_policy)
+BOOST_PARAMETER_TEMPLATE_KEYWORD(compile_policy)
+BOOST_PARAMETER_TEMPLATE_KEYWORD(fsm_check_policy)
+
+typedef ::boost::parameter::parameters<
+ ::boost::parameter::required< ::boost::msm::back::tag::front_end >
+ , ::boost::parameter::optional<
+ ::boost::parameter::deduced< ::boost::msm::back::tag::history_policy>, has_history_policy< ::boost::mpl::_ >
+ >
+ , ::boost::parameter::optional<
+ ::boost::parameter::deduced< ::boost::msm::back::tag::compile_policy>, has_compile_policy< ::boost::mpl::_ >
+ >
+ , ::boost::parameter::optional<
+ ::boost::parameter::deduced< ::boost::msm::back::tag::fsm_check_policy>, has_fsm_check< ::boost::mpl::_ >
+ >
+> state_machine_signature;
+
+
// library-containing class for state machines. Pass the actual FSM class as
// the Concrete parameter.
-template<class Derived,class HistoryPolicy=NoHistory,class CompilePolicy=favor_runtime_speed>
-class state_machine : public Derived
+// A0=Derived,A1=NoHistory,A2=CompilePolicy,A3=FsmCheckPolicy >
+template <
+ class A0
+ , class A1 = parameter::void_
+ , class A2 = parameter::void_
+ , class A3 = parameter::void_
+>
+class state_machine : //public Derived
+ public ::boost::parameter::binding<
+ typename state_machine_signature::bind<A0,A1,A2,A3>::type, ::boost::msm::back::tag::front_end
+ >::type
{
+public:
+ // Create ArgumentPack
+ typedef typename
+ state_machine_signature::bind<A0,A1,A2,A3>::type
+ state_machine_args;
+
+ // Extract first logical parameter.
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::front_end>::type Derived;
+
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::history_policy, NoHistory >::type HistoryPolicy;
+
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::compile_policy, favor_runtime_speed >::type CompilePolicy;
+
+ typedef typename ::boost::parameter::binding<
+ state_machine_args, ::boost::msm::back::tag::fsm_check_policy, no_fsm_check >::type FsmCheckPolicy;
+
+
private:
- typedef boost::msm::back::state_machine<Derived,
- HistoryPolicy,CompilePolicy> library_sm;
+
+ typedef boost::msm::back::state_machine<
+ A0,A1,A2,A3> library_sm;
typedef ::boost::function<
execute_return ()> transition_fct;
@@ -108,7 +164,7 @@
typedef bool (*flag_handler)(library_sm&);
// all state machines are friend with each other to allow embedding any of them in another fsm
- template <class ,class , class
+ template <class ,class , class, class
> friend class boost::msm::back::state_machine;
// helper to add, if needed, visitors to all states
@@ -1267,7 +1323,7 @@
}
// Construct with the default initial states
- state_machine<Derived,HistoryPolicy,CompilePolicy >()
+ state_machine<A0,A1,A2,A3 >()
:Derived()
,m_events_queue()
,m_deferred_events_queue()
@@ -1285,7 +1341,7 @@
fill_states(this);
}
template <class Expr>
- state_machine<Derived,HistoryPolicy,CompilePolicy >
+ state_machine<A0,A1,A2,A3 >
(Expr const& expr,typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type* =0)
:Derived()
,m_events_queue()
@@ -1313,7 +1369,7 @@
#define MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB(z, n, unused) ARG ## n t ## n
#define MSM_CONSTRUCTOR_HELPER_EXECUTE(z, n, unused) \
template <BOOST_PP_ENUM_PARAMS(n, class ARG)> \
- state_machine<Derived,HistoryPolicy,CompilePolicy \
+ state_machine<A0,A1,A2,A3 \
>(BOOST_PP_ENUM(n, MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB, ~ ), \
typename ::boost::disable_if<typename ::boost::proto::is_expr<ARG0>::type >::type* =0 ) \
:Derived(BOOST_PP_ENUM_PARAMS(n,t)) \
@@ -1331,7 +1387,7 @@
fill_states(this); \
} \
template <class Expr,BOOST_PP_ENUM_PARAMS(n, class ARG)> \
- state_machine<Derived,HistoryPolicy,CompilePolicy \
+ state_machine<A0,A1,A2,A3 \
>(Expr const& expr,BOOST_PP_ENUM(n, MSM_CONSTRUCTOR_HELPER_EXECUTE_SUB, ~ ), \
typename ::boost::enable_if<typename ::boost::proto::is_expr<Expr>::type >::type* =0 ) \
:Derived(BOOST_PP_ENUM_PARAMS(n,t)) \
@@ -1372,7 +1428,7 @@
}
return *this;
}
- state_machine<Derived,HistoryPolicy,CompilePolicy>
+ state_machine<A0,A1,A2,A3>
(library_sm const& rhs)
: Derived(rhs)
{
@@ -2046,6 +2102,26 @@
region_start_helper< ::boost::mpl::int_<0> >::do_start(this,incomingEvent);
}
+ template <class StateType>
+ struct find_region_id
+ {
+ template <int region>
+ struct In
+ {
+ enum {region_index=region};
+ };
+ // if the user provides no region, find it!
+ template<>
+ struct In<-1>
+ {
+ typedef typename build_orthogonal_regions<
+ stt,
+ typename Derived::initial_state
+ >::type all_regions;
+ enum {region_index= find_region_index<all_regions,StateType>::value };
+ };
+ enum {region_index = In<StateType::zone_index>::region_index };
+ };
// helper used to set the correct state as active state upon entry into a fsm
struct direct_event_start_helper
{
@@ -2074,10 +2150,10 @@
{
(static_cast<Derived*>(self))->on_entry(evt,fsm);
int state_id = get_state_id<stt,typename EventType::active_state::wrapped_entry>::value;
- BOOST_STATIC_ASSERT(EventType::active_state::zone_index >= 0);
- BOOST_STATIC_ASSERT(EventType::active_state::zone_index <= nr_regions::value);
+ BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index >= 0);
+ BOOST_STATIC_ASSERT(find_region_id<typename EventType::active_state::wrapped_entry>::region_index <= nr_regions::value);
// just set the correct zone, the others will be default/history initialized
- self->m_states[EventType::active_state::zone_index] = state_id;
+ self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
self->start(evt.m_event);
}
@@ -2113,7 +2189,7 @@
(static_cast<Derived*>(self))->on_entry(evt,fsm);
int state_id = get_state_id<stt,typename EventType::active_state::wrapped_entry>::value;
// given region starts with the entry pseudo state as active state
- self->m_states[EventType::active_state::zone_index] = state_id;
+ self->m_states[find_region_id<typename EventType::active_state::wrapped_entry>::region_index] = state_id;
self->start(evt.m_event);
// and we process the transition in the zone of the newly active state
// (entry pseudo states are, according to UML, a state connecting 1 transition outside to 1 inside
@@ -2131,9 +2207,9 @@
void operator()( ::boost::msm::wrap<StateType> const& )
{
int state_id = get_state_id<stt,typename StateType::wrapped_entry>::value;
- BOOST_STATIC_ASSERT(StateType::zone_index >= 0);
- BOOST_STATIC_ASSERT(StateType::zone_index <= nr_regions::value);
- helper_self->m_states[StateType::zone_index] = state_id;
+ BOOST_STATIC_ASSERT(find_region_id<typename StateType::wrapped_entry>::region_index >= 0);
+ BOOST_STATIC_ASSERT(find_region_id<typename StateType::wrapped_entry>::region_index <= nr_regions::value);
+ helper_self->m_states[find_region_id<typename StateType::wrapped_entry>::region_index] = state_id;
}
private:
library_sm* helper_self;
@@ -2322,6 +2398,9 @@
template <class ContainingSM>
void fill_states(ContainingSM* containing_sm=0)
{
+ // checks that regions are truly orthogonal
+ FsmCheckPolicy::template check_orthogonality<library_sm>();
+
BOOST_STATIC_CONSTANT(int, max_state = (mpl::size<state_list>::value));
// allocate the place without reallocation
m_visitors.fill_visitors(max_state);
Modified: trunk/boost/msm/front/euml/state_grammar.hpp
==============================================================================
--- trunk/boost/msm/front/euml/state_grammar.hpp (original)
+++ trunk/boost/msm/front/euml/state_grammar.hpp 2010-11-15 16:04:53 EST (Mon, 15 Nov 2010)
@@ -18,6 +18,7 @@
#include <boost/mpl/remove_if.hpp>
#include <boost/mpl/eval_if.hpp>
+#include <boost/mpl/assert.hpp>
#include <boost/msm/row_tags.hpp>
#include <boost/msm/front/common_states.hpp>
Boost-Commit list run by bdawes at acm.org, david.abrahams at rcn.com, gregod at cs.rpi.edu, cpdaniel at pacbell.net, john at johnmaddock.co.uk