コード例 #1
0
state_t::state_t(
	agent_t * target_agent,
	std::string state_name,
	state_t * parent_state,
	std::size_t nested_level,
	history_t state_history )
	:	m_target_agent{ target_agent }
	,	m_state_name( std::move(state_name) )
	,	m_parent_state{ parent_state }
	,	m_initial_substate{ nullptr }
	,	m_state_history{ state_history }
	,	m_last_active_substate{ nullptr }
	,	m_nested_level{ nested_level }
	,	m_substate_count{ 0 }
{
	if( parent_state )
	{
		// We should check the deep of nested states.
		if( m_nested_level >= max_deep )
			SO_5_THROW_EXCEPTION( rc_state_nesting_is_too_deep,
					"max nesting deep for agent states is " +
					std::to_string( max_deep ) );

		// Now we can safely mark parent state as composite.
		parent_state->m_substate_count += 1;
	}
}
コード例 #2
0
void
agent_t::so_change_state(
	const state_t & new_state )
{
	ensure_operation_is_on_working_thread( "so_change_state" );

	if( new_state.is_target( this ) )
	{
		auto actual_new_state = new_state.actual_state_to_enter();
		if( !( *actual_new_state == *m_current_state_ptr ) )
		{
			// New state differs from the current one.
			// Actual state switch must be performed.
			do_state_switch( *actual_new_state );

			// State listener should be informed.
			m_state_listener_controller->changed(
				*this,
				*m_current_state_ptr );
		}
	}
	else
		SO_5_THROW_EXCEPTION(
			rc_agent_unknown_state,
			"unable to switch agent to alien state "
			"(the state that doesn't belong to this agent)" );
}
コード例 #3
0
state_t &
state_t::time_limit(
	duration_t timeout,
	const state_t & state_to_switch )
{
	if( duration_t::zero() == timeout )
		SO_5_THROW_EXCEPTION( rc_invalid_time_limit_for_state,
				"zero can't be used as time limit for state '" +
				query_name() );

	// Old time limit must be dropped if it exists.
	drop_time_limit();
	m_time_limit.reset( new time_limit_t{ timeout, state_to_switch } );

	// If this state is active then new time limit must be activated.
	if( is_active() )
		so_5::details::do_with_rollback_on_exception(
			[&] {
				m_time_limit->set_up_limit_for_agent( *m_target_agent, *this );
			},
			[&] {
				// Time limit must be dropped because it is not activated
				// for the current state.
				drop_time_limit();
			} );

	return *this;
}
コード例 #4
0
void
ensure_queue_not_full( Q && queue )
	{
		if( queue.is_full() )
			SO_5_THROW_EXCEPTION(
					rc_msg_chain_is_full,
					"an attempt to push a message to full demand queue" );
	}
コード例 #5
0
void
ensure_queue_not_empty( Q && queue )
	{
		if( queue.is_empty() )
			SO_5_THROW_EXCEPTION(
					rc_msg_chain_is_empty,
					"an attempt to get message from empty demand queue" );
	}
コード例 #6
0
void
abstract_message_chain_t::remove_from_select(
	mchain_props::select_case_t & /*select_case*/ )
	{
		SO_5_THROW_EXCEPTION( rc_not_implemented,
				"abstract_message_chain_t::remove_from_select(select_case) is "
				"not implemented in abstract_message_chain_t class" );
	}
コード例 #7
0
mchain_props::extraction_status_t
abstract_message_chain_t::extract(
	mchain_props::demand_t & /*dest*/,
	mchain_props::select_case_t & /*select_case*/ )
	{
		SO_5_THROW_EXCEPTION( rc_not_implemented,
				"abstract_message_chain_t::extract(demand,select_case) is "
				"not implemented in abstract_message_chain_t class" );

		// Just to make compilers happy.
		return mchain_props::extraction_status_t::no_messages;
	}
コード例 #8
0
state_t::state_t(
	initial_substate_of parent,
	std::string state_name,
	history_t state_history )
	:	state_t{
			parent.m_parent_state->m_target_agent,
			std::move(state_name),
			parent.m_parent_state,
			parent.m_parent_state->m_nested_level + 1,
			state_history }
{
	if( m_parent_state->m_initial_substate )
		SO_5_THROW_EXCEPTION( rc_initial_substate_already_defined,
				"initial substate for state " + m_parent_state->query_name() +
				" is already defined: " +
				m_parent_state->m_initial_substate->query_name() );

	m_parent_state->m_initial_substate = this;
}
コード例 #9
0
const state_t *
state_t::actual_state_to_enter() const
{
	const state_t * s = this;
	while( 0 != s->m_substate_count )
	{
		if( s->m_last_active_substate )
			// Note: for states with shallow history m_last_active_substate
			// can point to composite substate. This substate must be
			// processed usual way with checking for substate count, presence
			// of initial substate and so on...
			s = s->m_last_active_substate;
		else if( !s->m_initial_substate )
			SO_5_THROW_EXCEPTION( rc_no_initial_substate,
					"there is no initial substate for composite state: " +
					query_name() );
		else
			s = s->m_initial_substate;
	}

	return s;
}