SObjectizer  5.5
Classes | Public Types | Public Member Functions | Static Public Attributes | Private Member Functions | Private Attributes | Friends | List of all members
so_5::state_t Class Referencefinal

Class for the representing agent state. More...

#include <state.hpp>

Classes

struct  time_limit_t
 

Public Types

enum  history_t { history_t::none, history_t::shallow, history_t::deep }
 Type of history for state. More...
 
using path_t = std::array< const state_t *, max_deep >
 A type for representation of state's path. More...
 
using on_enter_handler_t = std::function< void() >
 Type of function to be called on enter to the state. More...
 
using on_exit_handler_t = std::function< void() >
 Type of function to be called on exit from the state. More...
 
using duration_t = std::chrono::high_resolution_clock::duration
 Alias for duration type. More...
 

Public Member Functions

 state_t (agent_t *agent)
 
 state_t (agent_t *agent, history_t state_history)
 
 state_t (agent_t *agent, std::string state_name)
 
 state_t (agent_t *agent, std::string state_name, history_t state_history)
 
 state_t (initial_substate_of parent)
 Constructor for the case when state is the initial substate of some parent state. More...
 
 state_t (initial_substate_of parent, history_t state_history)
 Constructor for the case when state is the initial substate of some parent state. More...
 
 state_t (initial_substate_of parent, std::string state_name)
 Constructor for the case when state is the initial substate of some parent state. More...
 
 state_t (initial_substate_of parent, std::string state_name, history_t state_history)
 Constructor for the case when state is the initial substate of some parent state. More...
 
 state_t (substate_of parent)
 Constructor for the case when state is a substate of some parent state. More...
 
 state_t (substate_of parent, history_t state_history)
 Constructor for the case when state is a substate of some parent state. More...
 
 state_t (substate_of parent, std::string state_name)
 Constructor for the case when state is a substate of some parent state. More...
 
 state_t (substate_of parent, std::string state_name, history_t state_history)
 Constructor for the case when state is a substate of some parent state. More...
 
 state_t (state_t &&other)
 Move constructor. More...
 
 ~state_t ()
 
bool operator== (const state_t &state) const
 
bool operator!= (const state_t &state) const
 
std::string query_name () const
 Get textual name of the state. More...
 
bool is_target (const agent_t *agent) const
 Does agent owner of this state? More...
 
void activate () const
 Switch agent to that state. More...
 
bool is_active () const
 Is this state or any of its substates activated? More...
 
void clear_history ()
 Clear state history. More...
 
template<typename... Args>
const state_tevent (Args &&... args) const
 Helper for subscription of event handler in this state. More...
 
template<typename... Args>
state_tevent (Args &&... args)
 
template<typename... Args>
const state_tevent (mbox_t from, Args &&... args) const
 Helper for subscription of event handler in this state. More...
 
template<typename... Args>
state_tevent (mbox_t from, Args &&... args)
 
template<typename Signal , typename... Args>
const state_tevent (Args &&... args) const
 Helper for subscription of event handler in this state. More...
 
template<typename Signal , typename... Args>
state_tevent (Args &&... args)
 
template<typename Signal , typename... Args>
const state_tevent (mbox_t from, Args &&... args) const
 Helper for subscription of event handler in this state. More...
 
template<typename Signal , typename... Args>
state_tevent (mbox_t from, Args &&... args)
 
template<typename Msg >
bool has_subscription (const mbox_t &from) const
 Check the presence of a subscription. More...
 
template<typename Method_Pointer >
bool has_subscription (const mbox_t &from, Method_Pointer &&pfn) const
 Check the presence of a subscription. More...
 
template<typename Msg >
void drop_subscription (const mbox_t &from) const
 Drop subscription. More...
 
template<typename Method_Pointer >
void drop_subscription (const mbox_t &from, Method_Pointer &&pfn) const
 Drop subscription. More...
 
template<typename Msg >
const state_ttransfer_to_state (mbox_t from, const state_t &target_state) const
 An instruction for switching agent to the specified state and transfering event proceessing to new state. More...
 
template<typename Msg >
const state_ttransfer_to_state (const state_t &target_state) const
 An instruction for switching agent to the specified state and transfering event proceessing to new state. More...
 
template<typename Msg >
state_ttransfer_to_state (mbox_t from, const state_t &target_state)
 An instruction for switching agent to the specified state and transfering event proceessing to new state. More...
 
template<typename Msg >
state_ttransfer_to_state (const state_t &target_state)
 An instruction for switching agent to the specified state and transfering event proceessing to new state. More...
 
template<typename Msg >
const state_tjust_switch_to (mbox_t from, const state_t &target_state) const
 Define handler which only switches agent to the specified state. More...
 
template<typename Msg >
const state_tjust_switch_to (const state_t &target_state) const
 Define handler which only switches agent to the specified state. More...
 
template<typename Msg >
state_tjust_switch_to (mbox_t from, const state_t &target_state)
 Define handler which only switches agent to the specified state. More...
 
template<typename Msg >
state_tjust_switch_to (const state_t &target_state)
 Define handler which only switches agent to the specified state. More...
 
template<typename Msg >
const state_tsuppress () const
 Suppress processing of event in this state. More...
 
template<typename Msg >
const state_tsuppress (mbox_t from) const
 Suppress processing of event in this state. More...
 
template<typename Msg >
state_tsuppress ()
 Suppress processing of event in this state. More...
 
template<typename Msg >
state_tsuppress (mbox_t from)
 Suppress processing of event in this state. More...
 
Method for manupulation of enter/exit handlers.
state_ton_enter (on_enter_handler_t handler)
 Set on enter handler. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< Method_Pointer >::value, state_t &>::type on_enter (Method_Pointer pfn)
 Set on enter handler. More...
 
const on_enter_handler_ton_enter () const
 Query on enter handler. More...
 
state_ton_exit (on_exit_handler_t handler)
 Set on exit handler. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< Method_Pointer >::value, state_t &>::type on_exit (Method_Pointer pfn)
 Set on exit handler. More...
 
const on_exit_handler_ton_exit () const
 Query on enter handler. More...
 
Methods for dealing with state's time limit.
state_ttime_limit (duration_t timeout, const state_t &state_to_switch)
 Set up a time limit for the state. More...
 
state_tdrop_time_limit ()
 Drop time limit for the state if defined. More...
 

Static Public Attributes

static const std::size_t max_deep = 16
 Max deep of nested states. More...
 

Private Member Functions

 state_t (const state_t &)=delete
 
state_toperator= (const state_t &)=delete
 
 state_t (agent_t *target_agent, std::string state_name, state_t *parent_state, std::size_t nested_level, history_t state_history)
 Fully initialized constructor. More...
 
template<typename... Args>
const state_tsubscribe_message_handler (const mbox_t &from, Args &&... args) const
 A helper for handle-methods implementation. More...
 
template<typename Signal , typename... Args>
const state_tsubscribe_signal_handler (const mbox_t &from, Args &&... args) const
 A helper for handle-methods implementation. More...
 
Methods to be used by agents.
const state_tparent_state () const
 Get a parent state if exists. More...
 
const state_tactual_state_to_enter () const
 Find actual state to be activated for agent. More...
 
std::size_t nested_level () const
 Query nested level for the state. More...
 
void fill_path (path_t &path) const
 A helper method for building a path from top-level state to this state. More...
 
void update_history_in_parent_states () const
 A helper method which is used during state change for update state with history. More...
 
void handle_time_limit_on_enter () const
 A special handler of time limit to be used on entering into state. More...
 
void handle_time_limit_on_exit () const
 A special handler of time limit to be used on exiting from state. More...
 
void call_on_enter () const
 Call for on enter handler if defined. More...
 
void call_on_exit () const
 Call for on exit handler if defined. More...
 

Private Attributes

agent_t *const m_target_agent
 Owner of this state. More...
 
std::string m_state_name
 State name. More...
 
state_tm_parent_state
 Parent state. More...
 
const state_tm_initial_substate
 The initial substate. More...
 
history_t m_state_history
 Type of state history. More...
 
const state_tm_last_active_substate
 Last active substate. More...
 
std::size_t m_nested_level
 Nesting level for state. More...
 
size_t m_substate_count
 Number of substates. More...
 
on_enter_handler_t m_on_enter
 Handler for the enter to the state. More...
 
on_exit_handler_t m_on_exit
 Handler for the exit from the state. More...
 
std::unique_ptr< time_limit_tm_time_limit
 A definition of time limit for the state. More...
 

Friends

class agent_t
 

Detailed Description

Class for the representing agent state.

Attention
This class is not thread safe. It is designed to be used inside an owner agent only. For example:
class my_agent : public so_5::agent_t
{
state_t first_state{ this, "first" };
state_t second_state{ this, "second" };
...
public :
my_agent( context_t ctx ) : so_5::agent_t{ ctx }
{
// It is a safe usage of state.
first_state.on_enter( &my_agent::first_on_enter );
second_state.on_exit( &my_agent::second_on_exit );
...
}
virtual void so_define_agent() override
{
// It is a safe usage of state.
first_state.event( &my_agent::some_event_handler );
second_state.time_limit( std::chrono::seconds{20}, first_state );
second_state.event( [this]( const some_message & msg ) {
// It is also safe usage of state because event handler
// will be called on the context of agent's working thread.
second_state.drop_time_limit();
...
} );
}
void some_public_method()
{
// It is a safe usage if this method is called by the agent itself.
// This will be unsafe usage if this method is called from outside of
// the agent: a data damage or something like that can happen.
second_state.time_limit( std::chrono::seconds{30}, first_state );
}
...
};
Because of that be very careful during manipulation of agent's states outside of agent's event handlers.
Examples:
so_5/chstate/main.cpp.

Member Typedef Documentation

◆ duration_t

using so_5::state_t::duration_t = std::chrono::high_resolution_clock::duration

Alias for duration type.

Since
v.5.5.15

◆ on_enter_handler_t

using so_5::state_t::on_enter_handler_t = std::function< void() >

Type of function to be called on enter to the state.

Since
v.5.5.15
Attention
Handler must be noexcept function.

◆ on_exit_handler_t

using so_5::state_t::on_exit_handler_t = std::function< void() >

Type of function to be called on exit from the state.

Since
v.5.5.15
Attention
Handler must be noexcept function.

◆ path_t

using so_5::state_t::path_t = std::array< const state_t *, max_deep >

A type for representation of state's path.

Since
v.5.5.15
Note
Path contains pointer to the state itself (always the last item in the path) and pointers to all superstates. If state has no superstate the path will contains just one pointer to the state itself.

Member Enumeration Documentation

◆ history_t

Type of history for state.

Since
v.5.5.15
Enumerator
none 

State has no history.

shallow 

State has shallow history.

deep 

State has deep history.

Constructor & Destructor Documentation

◆ state_t() [1/15]

so_5::state_t::state_t ( const state_t )
privatedelete

◆ state_t() [2/15]

so_5::state_t::state_t ( agent_t agent)
Note
State name will be generated automaticaly.
Parameters
agentState owner.

◆ state_t() [3/15]

so_5::state_t::state_t ( agent_t agent,
history_t  state_history 
)
Since
v.5.5.15
Note
State name will be generated automaticaly.
Parameters
agentState owner.
state_historyType of state history.

◆ state_t() [4/15]

so_5::state_t::state_t ( agent_t agent,
std::string  state_name 
)
Parameters
agentState owner.
state_nameState name.

◆ state_t() [5/15]

so_5::state_t::state_t ( agent_t agent,
std::string  state_name,
history_t  state_history 
)
Since
v.5.5.15
Parameters
agentState owner.
state_nameState name.
state_historyType of state history.

◆ state_t() [6/15]

so_5::state_t::state_t ( initial_substate_of  parent)

Constructor for the case when state is the initial substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.

◆ state_t() [7/15]

so_5::state_t::state_t ( initial_substate_of  parent,
history_t  state_history 
)

Constructor for the case when state is the initial substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.
state_historyType of state history.

◆ state_t() [8/15]

so_5::state_t::state_t ( initial_substate_of  parent,
std::string  state_name 
)

Constructor for the case when state is the initial substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.
state_nameState name.

◆ state_t() [9/15]

so_5::state_t::state_t ( initial_substate_of  parent,
std::string  state_name,
history_t  state_history 
)

Constructor for the case when state is the initial substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.
state_nameState name.
state_historyType of state history.

◆ state_t() [10/15]

so_5::state_t::state_t ( substate_of  parent)

Constructor for the case when state is a substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.

◆ state_t() [11/15]

so_5::state_t::state_t ( substate_of  parent,
history_t  state_history 
)

Constructor for the case when state is a substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.
state_historyType of state history.

◆ state_t() [12/15]

so_5::state_t::state_t ( substate_of  parent,
std::string  state_name 
)

Constructor for the case when state is a substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.
state_nameState name.

◆ state_t() [13/15]

so_5::state_t::state_t ( substate_of  parent,
std::string  state_name,
history_t  state_history 
)

Constructor for the case when state is a substate of some parent state.

Since
v.5.5.15
Parameters
parentParent state.
state_nameState name.
state_historyType of state history.

◆ state_t() [14/15]

so_5::state_t::state_t ( state_t &&  other)

Move constructor.

Since
v.5.4.0

◆ ~state_t()

so_5::state_t::~state_t ( )

◆ state_t() [15/15]

so_5::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 
)
private

Fully initialized constructor.

Since
v.5.5.15
Parameters
target_agentOwner of this state.
state_nameName for this state.
parent_stateParent state. nullptr means that there is no parent state.
nested_levelNesting deep for this state. Value 0 means this state is a top-level state.
state_historyType of state history.

Member Function Documentation

◆ activate()

void so_5::state_t::activate ( ) const

Switch agent to that state.

Since
v.5.5.1

◆ actual_state_to_enter()

const state_t * so_5::state_t::actual_state_to_enter ( ) const
private

Find actual state to be activated for agent.

Since
v.5.5.15
Note
If (*this) is a composite state then actual state to enter will be its m_initial_substate (if m_initial_substate is a composite state then actual state to enter will be its m_initial_substate and so on).
If this state is a composite state with history then m_last_active_substate value will be used (if it is not nullptr).
Exceptions
exception_tif (*this) is a composite state but m_initial_substate is not defined.

◆ call_on_enter()

void so_5::state_t::call_on_enter ( ) const
inlineprivate

Call for on enter handler if defined.

Since
v.5.5.15

◆ call_on_exit()

void so_5::state_t::call_on_exit ( ) const
inlineprivate

Call for on exit handler if defined.

Since
v.5.5.15

◆ clear_history()

void so_5::state_t::clear_history ( )
inline

Clear state history.

Since
v.5.5.15
Note
Clears the history for this state only. History for any substates remains intact. For example:
class demo : public so_5::agent_t
{
state_t A{ this, "A", deep_history };
state_t B{ initial_substate_of{ A }, "B", shallow_history };
state_t C{ initial_substate_of{ B }, "C" };
state_t D{ substate_of{ B }, "D" };
state_t E{ this, "E" };
...
void some_event()
{
this >>= A; // The current state is "A.B.C"
// Because B is initial substate of A, and
// C is initial substate of B.
this >>= D; // The current state is "A.B.D".
this >>= E; // The current state is "E".
this >>= A; // The current state is "A.B.D" because deep history of A.
this >>= E;
A.clear_history();
this >>= A; // The current state is "A.B.D" because:
// B is the initial substate of A and B has shallow history;
// D is the last active substate of B.
}
};
Attention
This method is not thread safe. Be careful calling this method from outside of agent's working thread.

◆ drop_subscription() [1/2]

template<typename Msg >
void so_5::state_t::drop_subscription ( const mbox_t from) const

Drop subscription.

Drops the subscription for the message/signal of type Msg for the state (if this subscription is present). Do nothing if subscription is not exists.

Usage example:

class my_agent : public so_5::agent_t
{
state_t some_state{ this };
...
virtual void so_define_agent() override
{
some_state.event(some_mbox, &my_agent::some_handler);
...
}
...
void evt_some_another_handler()
{
// A subscription is no more needed.
some_state.drop_subscription<msg>(some_mbox);
}
};
Note
This method should be called only from the working context of the agent.
Since
v.5.5.19.5

◆ drop_subscription() [2/2]

template<typename Method_Pointer >
void so_5::state_t::drop_subscription ( const mbox_t from,
Method_Pointer &&  pfn 
) const

Drop subscription.

Drops the subscription for the message/signal for the state (if this subscription is present). Do nothing if subscription is not exists.

Type of a message is deduced from event handler signature.

Usage example:

class my_agent : public so_5::agent_t
{
state_t some_state{ this };
...
virtual void so_define_agent() override
{
some_state.event(some_mbox, &my_agent::some_handler);
...
}
...
void some_another_handler()
{
// A subscription is no more needed.
some_state.drop_subscription(some_mbox, &my_agent::some_handler);
}
void some_handler(mhood_t<msg> cmd)
{
...
}
};
Note
This method should be called only from the working context of the agent.
Since
v.5.5.19.5

◆ drop_time_limit()

state_t & so_5::state_t::drop_time_limit ( )

Drop time limit for the state if defined.

Since
v.5.5.15
Note
Do nothing if a time limit is not defined.
This method can be useful if there is need to refine state defined in the parent class:
class parent : public so_5::agent_t
{
protected :
state_t dialog{ this, "dialog" };
state_t show_err{ this, "err" };
...
public :
virtual void so_define_agent() override
{
dialog
.on_enter( [this] { m_display.clear(); } )
.event( [this]( const user_input & msg ) {
try_handle_input( msg );
if( some_error() ) {
m_error = error_description();
this >>= show_err;
}
} )
...; // Other handlers.
show_err
.on_enter( [this] { m_display.show( m_error ); } )
.time_limit( std::chrono::seconds{2}, dialog );
}
...
protected :
display m_display;
std::string m_error;
...
};
class child : public parent
{
public :
virtual void so_define_agent() override
{
parent::so_define_agent();
show_err
// Switching from show_err to dialog must be done
// only by pressing "cancel" or "ok" buttons.
// Automatic switching after 2s must be disabled.
.drop_time_limit()
.just_switch_to< key_cancel >( dialog )
.just_switch_to< key_on >( dialog );
}
...
};
This method can be called when agents is already in that state. Automatic switching will be disabled. To reenable automatic switching time_limit() method must be called again:
class demo : public so_5::agent_t
{
state_t dialog{ this, "dialog" };
state_t show_err{ this, "err" };
...
public :
virtual void so_define_agent() override
{
dialog
.on_enter( [this] { m_display.clear(); } )
.event( [this]( const user_input & msg ) {
try_handle_input( msg );
if( some_error() ) {
m_error = error_description();
this >>= show_err;
}
} )
...; // Other handlers.
show_err
.on_enter( [this] { m_display.show( m_error ); } )
// By default state will be switched after 2s.
.time_limit( std::chrono::seconds{2}, dialog )
.event< key_pause >( [this] {
// Disable automatic switching.
show_err.drop_time_limit();
} )
.event< key_continue >( [this] {
// Automatic switching is reenabled.
show_err.time_limit( std::chrono::seconds{2}, dialog );
...
} );
}
...
private :
display m_display;
std::string m_error;
...
};

◆ event() [1/8]

template<typename... Args>
const state_t & so_5::state_t::event ( Args &&...  args) const

Helper for subscription of event handler in this state.

Since
v.5.5.1
Note
This method must be used for messages which are sent to agent's direct mbox.
Usage example
class my_agent : public so_5::agent_t
{
const so_5::state_t st_normal = so_make_state();
public :
...
virtual void so_define_agent() override {
st_normal.event( [=]( const msg_reconfig & evt ) { ... } );
st_normal.event( &my_agent::evt_shutdown );
...
}
};
Examples:
so_5/chameneos_prealloc_msgs/main.cpp, so_5/chameneos_simple/main.cpp, so_5/chstate_msg_tracing/main.cpp, so_5/collector_many_performers/main.cpp, so_5/collector_performer_pair/main.cpp, so_5/coop_notification/main.cpp, so_5/coop_user_resources/main.cpp, so_5/ping_pong_with_owner/main.cpp, so_5/private_dispatcher_for_children/main.cpp, so_5/private_dispatcher_hello/main.cpp, so_5/private_dispatcher_restarts/main.cpp, so_5/queue_size_stats/main.cpp, so_5/redirect_and_transform/main.cpp, so_5/simple_message_deadline/main.cpp, and so_5/work_generation/main.cpp.

◆ event() [2/8]

template<typename... Args>
state_t& so_5::state_t::event ( Args &&...  args)
inline
Since
v.5.5.15

◆ event() [3/8]

template<typename... Args>
const state_t & so_5::state_t::event ( mbox_t  from,
Args &&...  args 
) const

Helper for subscription of event handler in this state.

Since
v.5.5.1
Note
This method must be used for messages which are sent to from message-box.
Usage example
class my_agent : public so_5::agent_t
{
const so_5::state_t st_normal = so_make_state();
public :
...
virtual void so_define_agent() override {
st_normal.event( m_owner, [=]( const msg_reconfig & evt ) { ... } );
st_normal.event( m_owner, &my_agent::evt_shutdown );
...
}
private :
so_5::mbox_t m_owner;
};

◆ event() [4/8]

template<typename... Args>
state_t& so_5::state_t::event ( mbox_t  from,
Args &&...  args 
)
inline
Since
v.5.5.15

◆ event() [5/8]

template<typename Signal, typename... Args>
const state_t & so_5::state_t::event ( Args &&...  args) const

Helper for subscription of event handler in this state.

Since
v.5.5.1
Note
This method must be used for signal subscriptions.
This method must be used for messages which are sent to agent's direct mbox.
Usage example
class my_agent : public so_5::agent_t
{
const so_5::state_t st_normal = so_make_state();
public :
...
virtual void so_define_agent() override {
st_normal.event< msg_reconfig >( [=] { ... } );
st_normal.event< msg_shutdown >( &my_agent::evt_shutdown );
...
}
};

◆ event() [6/8]

template<typename Signal , typename... Args>
state_t& so_5::state_t::event ( Args &&...  args)
inline
Since
v.5.5.15

◆ event() [7/8]

template<typename Signal, typename... Args>
const state_t & so_5::state_t::event ( mbox_t  from,
Args &&...  args 
) const

Helper for subscription of event handler in this state.

Since
v.5.5.1
Note
This method must be used for signal subscriptions.
This method must be used for messages which are sent to from message-box.
Usage example
class my_agent : public so_5::agent_t
{
const so_5::state_t st_normal = so_make_state();
public :
...
virtual void so_define_agent() override {
st_normal.event< msg_reconfig >( m_owner, [=] { ... } );
st_normal.event< msg_shutdown >( m_owner, &my_agent::evt_shutdown );
...
}
private :
so_5::mbox_t m_owner;
};

◆ event() [8/8]

template<typename Signal , typename... Args>
state_t& so_5::state_t::event ( mbox_t  from,
Args &&...  args 
)
inline
Since
v.5.5.15

◆ fill_path()

void so_5::state_t::fill_path ( path_t path) const
inlineprivate

A helper method for building a path from top-level state to this state.

Since
v.5.5.15

◆ handle_time_limit_on_enter()

void so_5::state_t::handle_time_limit_on_enter ( ) const
private

A special handler of time limit to be used on entering into state.

Since
v.5.5.15
Attention
This method must be called only if m_time_limit is not null.

◆ handle_time_limit_on_exit()

void so_5::state_t::handle_time_limit_on_exit ( ) const
private

A special handler of time limit to be used on exiting from state.

Since
v.5.5.15
Attention
This method must be called only if m_time_limit is not null.

◆ has_subscription() [1/2]

template<typename Msg >
bool so_5::state_t::has_subscription ( const mbox_t from) const

Check the presence of a subscription.

Returns
true if subscription is present.

Usage example:

void my_agent::evt_create_new_subscription(mhood_t<data_source> cmd)
{
// cmd can contain mbox we have already subscribed to.
// If we just call so_subscribe() then an exception can be thrown.
// Because of that check the presence of subscription first.
if(!some_state.has_subscription<some_message>(cmd->mbox()))
{
// There is no subscription yet. New subscription can be
// created.
some_state.event(cmd->mbox(), ...);
}
}
See also
so_5::agent_t::so_has_subscription
Since
v.5.5.19.5

◆ has_subscription() [2/2]

template<typename Method_Pointer >
bool so_5::state_t::has_subscription ( const mbox_t from,
Method_Pointer &&  pfn 
) const

Check the presence of a subscription.

Type is deduced from the signature of event_handler.

Returns
true if subscription is present.

Usage example:

void my_agent::evt_create_new_subscription(mhood_t<data_source> cmd)
{
// cmd can contain mbox we have already subscribed to.
// If we just call so_subscribe() then an exception can be thrown.
// Because of that check the presence of subscription first.
if(!some_state.has_subscription(cmd->mbox(), &my_agent::some_event))
{
// There is no subscription yet. New subscription can be
// created.
some_state.event(cmd->mbox(), ...);
}
}
See also
so_5::agent_t::so_has_subscription
Since
v.5.5.19.5

◆ is_active()

bool so_5::state_t::is_active ( ) const
inline

Is this state or any of its substates activated?

Since
v.5.5.15
Note
See so_5::agent_t::so_is_active_state() for more details. This method is just a thin wrapper around agent_t::so_is_active_state().

◆ is_target()

bool so_5::state_t::is_target ( const agent_t agent) const

Does agent owner of this state?

◆ just_switch_to() [1/4]

template<typename Msg >
const state_t & so_5::state_t::just_switch_to ( mbox_t  from,
const state_t target_state 
) const

Define handler which only switches agent to the specified state.

Since
v.5.5.15
Note
Defines a reaction to message/signal which is going from message box from.
This method differes from transfer_to_state() method: just_switch_to() changes state of the agent, but there will not be a look for event handler for message/signal in the new state. It means that just_switch_to() is just a shorthand for:
virtual void demo::so_define_agent() override
{
some_state.event< some_signal >( from, [this]{ this >>= S2; } );
}
With just_switch_to() this code can looks like:
virtual void demo::so_define_agent() override
{
some_state.just_switch_to< some_signal >( from, S2 );
}

◆ just_switch_to() [2/4]

template<typename Msg >
const state_t & so_5::state_t::just_switch_to ( const state_t target_state) const

Define handler which only switches agent to the specified state.

Since
v.5.5.15
Note
Defines a reaction to message/signal which is going from agent's direct mbox.
This method differes from transfer_to_state() method: just_switch_to() changes state of the agent, but there will not be a look for event handler for message/signal in the new state. It means that just_switch_to() is just a shorthand for:
virtual void demo::so_define_agent() override
{
some_state.event< some_signal >( [this]{ this >>= S2; } );
}
With just_switch_to() this code can looks like:
virtual void demo::so_define_agent() override
{
some_state.just_switch_to< some_signal >( S2 );
}

◆ just_switch_to() [3/4]

template<typename Msg >
state_t& so_5::state_t::just_switch_to ( mbox_t  from,
const state_t target_state 
)
inline

Define handler which only switches agent to the specified state.

Since
v.5.5.15
Note
Defines a reaction to message/signal which is going from message box from.
This method differes from transfer_to_state() method: just_switch_to() changes state of the agent, but there will not be a look for event handler for message/signal in the new state. It means that just_switch_to() is just a shorthand for:
virtual void demo::so_define_agent() override
{
some_state.event< some_signal >( from, [this]{ this >>= S2; } );
}
With just_switch_to() this code can looks like:
virtual void demo::so_define_agent() override
{
some_state.just_switch_to< some_signal >( from, S2 );
}

◆ just_switch_to() [4/4]

template<typename Msg >
state_t& so_5::state_t::just_switch_to ( const state_t target_state)
inline

Define handler which only switches agent to the specified state.

Since
v.5.5.15
Note
Defines a reaction to message/signal which is going from agent's direct mbox.
This method differes from transfer_to_state() method: just_switch_to() changes state of the agent, but there will not be a look for event handler for message/signal in the new state. It means that just_switch_to() is just a shorthand for:
virtual void demo::so_define_agent() override
{
some_state.event< some_signal >( [this]{ this >>= S2; } );
}
With just_switch_to() this code can looks like:
virtual void demo::so_define_agent() override
{
some_state.just_switch_to< some_signal >( S2 );
}

◆ nested_level()

std::size_t so_5::state_t::nested_level ( ) const
inlineprivate

Query nested level for the state.

Since
v.5.5.15

◆ on_enter() [1/3]

state_t& so_5::state_t::on_enter ( on_enter_handler_t  handler)
inline

Set on enter handler.

Since
v.5.5.15
Attention
Handler must be noexcept function. If handler throws an exception the whole application will be aborted.
Usage example:
class demo : public so_5::agent_t
{
state_t number_accumulation{ this, "accumulation" };
...
public :
virtual void so_define_agent() override
{
number_accumulation
.on_enter( [this] { m_number.clear(); } )
.event( [this]( const next_digit & msg ) {
m_number += msg.m_digit;
} );
...
}
...
private :
std::string m_number;
};

◆ on_enter() [2/3]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< Method_Pointer >::value, state_t &>::type so_5::state_t::on_enter ( Method_Pointer  pfn)

Set on enter handler.

Since
v.5.5.15
Attention
Handler must be noexcept function. If handler throws an exception the whole application will be aborted.
Usage example:
class demo : public so_5::agent_t
{
state_t number_accumulation{ this, "accumulation" };
...
public :
virtual void so_define_agent() override
{
number_accumulation
.on_enter( &demo::accumulation_on_enter )
.event( [this]( const next_digit & msg ) {
m_number += msg.m_digit;
} );
...
}
...
private :
std::string m_number;
...
void accumulation_on_enter()
{
m_number.clear();
...
}
};

◆ on_enter() [3/3]

const on_enter_handler_t& so_5::state_t::on_enter ( ) const
inline

Query on enter handler.

Since
v.5.5.15
Note
This method can be useful if there is a need to refine handler defined in the base class:
class parent : public so_5::agent_t
{
protected :
state_t some_state{ this, ... };
public :
virtual void so_define_agent() override
{
some_state.on_enter( [this] {
... // Some action.
} );
}
...
};
class child : public parent
{
public :
virtual void so_define_agent() override
{
// Calling so_define_agent from base class.
parent::so_define_agent();
// Refine on_enter handler for state from parent class.
auto old_handler = some_state.on_enter();
some_state.on_enter( [this, old_handler] {
old_handler(); // Calling the old handler.
... // Some addition action.
} );
}
...
};

◆ on_exit() [1/3]

state_t& so_5::state_t::on_exit ( on_exit_handler_t  handler)
inline

Set on exit handler.

Since
v.5.5.15
Attention
Handler must be noexcept function. If handler throws an exception the whole application will be aborted.
Usage example:
class demo : public so_5::agent_t
{
state_t dialog{ this, "dialog" };
...
public :
virtual void so_define_agent() override
{
dialog
.on_exit( [this] { m_display.turn_off(); } )
.event( [this]( const user_input & msg ) {...} );
...
}
...
private :
display m_display;
};

◆ on_exit() [2/3]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< Method_Pointer >::value, state_t &>::type so_5::state_t::on_exit ( Method_Pointer  pfn)

Set on exit handler.

Since
v.5.5.15
Attention
Handler must be noexcept function. If handler throws an exception the whole application will be aborted.
Usage example:
class demo : public so_5::agent_t
{
state_t dialog{ this, "dialog" };
...
public :
virtual void so_define_agent() override
{
dialog
.on_exit( &demo::dialog_on_exit )
.event( [this]( const user_input & msg ) {...} );
...
}
...
private :
display m_display;
...
void dialog_on_exit()
{
m_display.turn_off();
...
}
};

◆ on_exit() [3/3]

const on_exit_handler_t& so_5::state_t::on_exit ( ) const
inline

Query on enter handler.

Since
v.5.5.15
Note
This method can be useful if there is a need to refine handler defined in the base class:
class parent : public so_5::agent_t
{
protected :
state_t some_state{ this, ... };
public :
virtual void so_define_agent() override
{
some_state.on_exit( [this] {
... // Some action.
} );
}
...
};
class child : public parent
{
public :
virtual void so_define_agent() override
{
// Calling so_define_agent from base class.
parent::so_define_agent();
// Refine on_enter handler for state from parent class.
auto old_handler = some_state.on_exit();
some_state.on_exit( [this, old_handler] {
... // Some addition action.
old_handler(); // Calling the old handler.
} );
}
...
};

◆ operator!=()

bool so_5::state_t::operator!= ( const state_t state) const
inline
Since
v.5.5.20.1

◆ operator=()

state_t& so_5::state_t::operator= ( const state_t )
privatedelete

◆ operator==()

bool so_5::state_t::operator== ( const state_t state) const

◆ parent_state()

const state_t* so_5::state_t::parent_state ( ) const
inlineprivate

Get a parent state if exists.

Since
v.5.5.15

◆ query_name()

std::string so_5::state_t::query_name ( ) const

Get textual name of the state.

Note
The return type is changed in v.5.5.15: now it is a std::string object, not a const reference to some value inside state_t object.
Examples:
so_5/chstate/main.cpp.

◆ subscribe_message_handler()

template<typename... Args>
const state_t & so_5::state_t::subscribe_message_handler ( const mbox_t from,
Args &&...  args 
) const
private

A helper for handle-methods implementation.

Since
v.5.5.1

◆ subscribe_signal_handler()

template<typename Signal , typename... Args>
const state_t & so_5::state_t::subscribe_signal_handler ( const mbox_t from,
Args &&...  args 
) const
private

A helper for handle-methods implementation.

Since
v.5.5.1

◆ suppress() [1/4]

template<typename Msg >
const state_t & so_5::state_t::suppress ( ) const

Suppress processing of event in this state.

Since
v.5.5.15
Note
Suppresses message/signal which is going from agent's direct mbox.
This method allows to disable passing of event to event handlers from parent states. For example:
class demo : public so_5::agent_t
{
const state_t S1{ this, "1" };
const state_t S2{ initial_substate_of{ S1 }, "2" };
const state_t S3{ initial_substate_of{ S2 }, "3" };
public :
virtual void so_define_agent() override
{
S1
// Default event handler which will be inherited by states S2 and S3.
.event< msg1 >(...)
.event< msg2 >(...)
.event< msg3 >(...);
S2
// A special handler for msg1.
// For msg2 and msg3 event handlers from state S1 will be used.
.event< msg1 >(...);
S3
// Message msg1 will be suppressed. It will be simply ignored.
// No events from states S1 and S2 will be called.
.suppress< msg1 >()
// The same for msg2.
.suppress< msg2 >()
// A special handler for msg3. Overrides handler from state S1.
.event< msg3 >(...);
}
};

◆ suppress() [2/4]

template<typename Msg >
const state_t & so_5::state_t::suppress ( mbox_t  from) const

Suppress processing of event in this state.

Since
v.5.5.15
Note
Suppresses message/signal which is going from message box from.
This method allows to disable passing of event to event handlers from parent states. For example:
class demo : public so_5::agent_t
{
const state_t S1{ this, "1" };
const state_t S2{ initial_substate_of{ S1 }, "2" };
const state_t S3{ initial_substate_of{ S2 }, "3" };
public :
virtual void so_define_agent() override
{
S1
// Default event handler which will be inherited by states S2 and S3.
.event< msg1 >( some_mbox, ...)
.event< msg2 >( some_mbox, ...)
.event< msg3 >( some_mbox, ...);
S2
// A special handler for msg1.
// For msg2 and msg3 event handlers from state S1 will be used.
.event< msg1 >( some_mbox, ...);
S3
// Message msg1 will be suppressed. It will be simply ignored.
// No events from states S1 and S2 will be called.
.suppress< msg1 >( some_mbox )
// The same for msg2.
.suppress< msg2 >( some_mbox )
// A special handler for msg3. Overrides handler from state S1.
.event< msg3 >( some_mbox );
}
};

◆ suppress() [3/4]

template<typename Msg >
state_t& so_5::state_t::suppress ( )
inline

Suppress processing of event in this state.

Since
v.5.5.15
Note
Suppresses message/signal which is going from agent's direct mbox.
This method allows to disable passing of event to event handlers from parent states. For example:
class demo : public so_5::agent_t
{
state_t S1{ this, "1" };
state_t S2{ initial_substate_of{ S1 }, "2" };
state_t S3{ initial_substate_of{ S2 }, "3" };
public :
virtual void so_define_agent() override
{
S1
// Default event handler which will be inherited by states S2 and S3.
.event< msg1 >(...)
.event< msg2 >(...)
.event< msg3 >(...);
S2
// A special handler for msg1.
// For msg2 and msg3 event handlers from state S1 will be used.
.event< msg1 >(...);
S3
// Message msg1 will be suppressed. It will be simply ignored.
// No events from states S1 and S2 will be called.
.suppress< msg1 >()
// The same for msg2.
.suppress< msg2 >()
// A special handler for msg3. Overrides handler from state S1.
.event< msg3 >(...);
}
};

◆ suppress() [4/4]

template<typename Msg >
state_t& so_5::state_t::suppress ( mbox_t  from)
inline

Suppress processing of event in this state.

Since
v.5.5.15
Note
Suppresses message/signal which is going from message box from.
This method allows to disable passing of event to event handlers from parent states. For example:
class demo : public so_5::agent_t
{
state_t S1{ this, "1" };
state_t S2{ initial_substate_of{ S1 }, "2" };
state_t S3{ initial_substate_of{ S2 }, "3" };
public :
virtual void so_define_agent() override
{
S1
// Default event handler which will be inherited by states S2 and S3.
.event< msg1 >( some_mbox, ...)
.event< msg2 >( some_mbox, ...)
.event< msg3 >( some_mbox, ...);
S2
// A special handler for msg1.
// For msg2 and msg3 event handlers from state S1 will be used.
.event< msg1 >( some_mbox, ...);
S3
// Message msg1 will be suppressed. It will be simply ignored.
// No events from states S1 and S2 will be called.
.suppress< msg1 >( some_mbox )
// The same for msg2.
.suppress< msg2 >( some_mbox )
// A special handler for msg3. Overrides handler from state S1.
.event< msg3 >( some_mbox );
}
};

◆ time_limit()

state_t & so_5::state_t::time_limit ( duration_t  timeout,
const state_t state_to_switch 
)

Set up a time limit for the state.

Since
v.5.5.15
Note
Agent will automatically switched to state_to_switch after timeout spent in the current state.
Usage example:
class demo : public so_5::agent_t
{
state_t dialog{ this, "dialog" };
state_t show_err{ this, "err" };
...
public :
virtual void so_define_agent() override
{
dialog
.on_enter( [this] { m_display.clear(); } )
.event( [this]( const user_input & msg ) {
try_handle_input( msg );
if( some_error() ) {
m_error = error_description();
this >>= show_err;
}
} )
...; // Other handlers.
show_err
.on_enter( [this] { m_display.show( m_error ); } )
.time_limit( std::chrono::seconds{2}, dialog );
}
...
private :
display m_display;
std::string m_error;
...
};
Note
If S.time_limit() is called when S is active state then time_limit for that state will be reset and time for the state S will be counted from zero.
Parameters
timeoutMax duration of time for staying in this state.
state_to_switchA new state to be switched to.

◆ transfer_to_state() [1/4]

template<typename Msg >
const state_t & so_5::state_t::transfer_to_state ( mbox_t  from,
const state_t target_state 
) const

An instruction for switching agent to the specified state and transfering event proceessing to new state.

Since
v.5.5.15
Note
Transfers processing of message/signal which is going from message box from.
Usage example:
class device : public so_5::agent_t {
const state_t off{ this, "off" };
const state_t on{ this, "on" };
public :
virtual void so_define_agent() override {
.transfer_to_state< key_on >( some_mbox, on )
.transfer_to_state< key_info >( some_mbox, on );
...
}
...
};
Note
For more details see subscription_bind_t::transfer_to_state().
Since v.5.5.22.1 actual execution of transfer_to_state operation can raise so_5::exception_t with so_5::rc_transfer_to_state_loop error code if a loop in transfer_to_state is detected.

◆ transfer_to_state() [2/4]

template<typename Msg >
const state_t & so_5::state_t::transfer_to_state ( const state_t target_state) const

An instruction for switching agent to the specified state and transfering event proceessing to new state.

Since
v.5.5.15
Note
Transfers processing of message/signal which is going from agent's direct mbox.
Usage example:
class device : public so_5::agent_t {
const state_t off{ this, "off" };
const state_t on{ this, "on" };
public :
virtual void so_define_agent() override {
.transfer_to_state< key_on >( on )
.transfer_to_state< key_info >( on );
...
}
...
};
Note
For more details see subscription_bind_t::transfer_to_state().
Since v.5.5.22.1 actual execution of transfer_to_state operation can raise so_5::exception_t with so_5::rc_transfer_to_state_loop error code if a loop in transfer_to_state is detected.

◆ transfer_to_state() [3/4]

template<typename Msg >
state_t& so_5::state_t::transfer_to_state ( mbox_t  from,
const state_t target_state 
)
inline

An instruction for switching agent to the specified state and transfering event proceessing to new state.

Since
v.5.5.15
Note
Transfers processing of message/signal which is going from message box from.
Usage example:
class device : public so_5::agent_t {
state_t off{ this, "off" };
state_t on{ this, "on" };
public :
virtual void so_define_agent() override {
.transfer_to_state< key_on >( some_mbox, on )
.transfer_to_state< key_info >( some_mbox, on );
...
}
...
};
Note
For more details see subscription_bind_t::transfer_to_state().
Since v.5.5.22.1 actual execution of transfer_to_state operation can raise so_5::exception_t with so_5::rc_transfer_to_state_loop error code if a loop in transfer_to_state is detected.

◆ transfer_to_state() [4/4]

template<typename Msg >
state_t& so_5::state_t::transfer_to_state ( const state_t target_state)
inline

An instruction for switching agent to the specified state and transfering event proceessing to new state.

Since
v.5.5.15
Note
Transfers processing of message/signal which is going from agent's direct mbox.
Usage example:
class device : public so_5::agent_t {
state_t off{ this, "off" };
state_t on{ this, "on" };
public :
virtual void so_define_agent() override {
.transfer_to_state< key_on >( on )
.transfer_to_state< key_info >( on );
...
}
...
};
Note
For more details see subscription_bind_t::transfer_to_state().
Since v.5.5.22.1 actual execution of transfer_to_state operation can raise so_5::exception_t with so_5::rc_transfer_to_state_loop error code if a loop in transfer_to_state is detected.

◆ update_history_in_parent_states()

void so_5::state_t::update_history_in_parent_states ( ) const
private

A helper method which is used during state change for update state with history.

Since
v.5.5.15

Friends And Related Function Documentation

◆ agent_t

friend class agent_t
friend
Deprecated:
Will be removed in v.5.6.0. Use so_5::agent_t instead.

Member Data Documentation

◆ m_initial_substate

const state_t* so_5::state_t::m_initial_substate
private

The initial substate.

Since
v.5.5.15
Note
Value nullptr means that state has no initial substate. If m_substate_count == 0 it is normal. It means that state is not a composite state. But if m_substate_count != 0 the value nullptr means that state description is incorrect.

◆ m_last_active_substate

const state_t* so_5::state_t::m_last_active_substate
private

Last active substate.

Since
v.5.5.15
Note
This attribute is used only if m_state_history != history_t::none. It holds a pointer to last active substate of this composite state.

◆ m_nested_level

std::size_t so_5::state_t::m_nested_level
private

Nesting level for state.

Since
v.5.5.15
Note
Value 0 means that state is a top-level state.

◆ m_on_enter

on_enter_handler_t so_5::state_t::m_on_enter
private

Handler for the enter to the state.

Since
v.5.5.15

◆ m_on_exit

on_exit_handler_t so_5::state_t::m_on_exit
private

Handler for the exit from the state.

Since
v.5.5.15

◆ m_parent_state

state_t* so_5::state_t::m_parent_state
private

Parent state.

Since
v.5.5.15
Note
Value nullptr means that state is a top-level state and has no parent state.
This pointer is not const because some modification of parent state must be performed via that pointer.

◆ m_state_history

history_t so_5::state_t::m_state_history
private

Type of state history.

Since
v.5.5.15

◆ m_state_name

std::string so_5::state_t::m_state_name
private

State name.

Note
Since v.5.5.15 has empty value for anonymous state.

◆ m_substate_count

size_t so_5::state_t::m_substate_count
private

Number of substates.

Since
v.5.5.15
Note
Value 0 means that state is not composite state and has no any substates.

◆ m_target_agent

agent_t* const so_5::state_t::m_target_agent
private

Owner of this state.

◆ m_time_limit

std::unique_ptr< time_limit_t > so_5::state_t::m_time_limit
private

A definition of time limit for the state.

Since
v.5.5.15
Note
Value nullptr means that time limit is not set.

◆ max_deep

const std::size_t so_5::state_t::max_deep = 16
static

Max deep of nested states.

Since
v.5.5.15

The documentation for this class was generated from the following files: