SObjectizer  5.7
Public Types | Public Member Functions | Static Public Member Functions | Static Public Attributes | Private Types | Private Member Functions | Static Private Member Functions | Private Attributes | Friends | List of all members
so_5::agent_t Class Reference

A base class for agents. More...

#include <agent.hpp>

Inheritance diagram for so_5::agent_t:
so_5::atomic_refcounted_t so_5::message_limit::message_limit_methods_mixin_t

Public Types

using context_t = so_5::agent_context_t
 Short alias for agent_context. More...
 
using state_t = so_5::state_t
 Short alias for so_5::state_t. More...
 
template<typename T >
using mhood_t = so_5::mhood_t< T >
 Short alias for so_5::mhood_t. More...
 
template<typename T >
using mutable_mhood_t = so_5::mutable_mhood_t< T >
 Short alias for so_5::mutable_mhood_t. More...
 
using initial_substate_of = so_5::initial_substate_of
 Short alias for so_5::initial_substate_of. More...
 
using substate_of = so_5::substate_of
 Short alias for so_5::substate_of. More...
 
- Public Types inherited from so_5::message_limit::message_limit_methods_mixin_t
using any_unspecified_message = ::so_5::message_limit::any_unspecified_message
 

Public Member Functions

 agent_t (environment_t &env)
 Constructor. More...
 
 agent_t (environment_t &env, agent_tuning_options_t tuning_options)
 Constructor which allows specification of agent's tuning options. More...
 
 agent_t (context_t ctx)
 Constructor which simplifies agent construction with or without agent's tuning options. More...
 
virtual ~agent_t ()
 
const agent_tself_ptr () const
 Get the raw pointer of itself. More...
 
agent_tself_ptr ()
 
virtual void so_evt_start ()
 Hook on agent start inside SObjectizer. More...
 
virtual void so_evt_finish ()
 Hook of agent finish in SObjectizer. More...
 
const state_tso_current_state () const
 Access to the current agent state. More...
 
bool so_is_active_state (const state_t &state_to_check) const noexcept
 Is a state activated? More...
 
void so_add_nondestroyable_listener (agent_state_listener_t &state_listener)
 Add a state listener to the agent. More...
 
void so_add_destroyable_listener (agent_state_listener_unique_ptr_t state_listener)
 Add a state listener to the agent. More...
 
virtual exception_reaction_t so_exception_reaction () const
 A reaction from SObjectizer to an exception from agent's event. More...
 
void so_switch_to_awaiting_deregistration_state ()
 Switching agent to special state in case of unhandled exception. More...
 
const mbox_tso_direct_mbox () const
 Get the agent's direct mbox. More...
 
mbox_t so_make_new_direct_mbox ()
 Create a new direct mbox for that agent. More...
 
environment_tso_environment () const
 Access to the SObjectizer Environment which this agent is belong. More...
 
coop_handle_t so_coop () const
 Get a handle of agent's coop. More...
 
void so_bind_to_dispatcher (event_queue_t &queue) noexcept
 Binding agent to the dispatcher. More...
 
void so_deregister_agent_coop (int dereg_reason)
 A helper method for deregistering agent's coop. More...
 
void so_deregister_agent_coop_normally ()
 A helper method for deregistering agent's coop in case of normal deregistration. More...
 
Changing agent's state.
void so_change_state (const state_t &new_state)
 Change the current state of the agent. More...
 
void so_deactivate_agent ()
 Deactivate the agent. More...
 
Subscription methods.
subscription_bind_t so_subscribe (const mbox_t &mbox_ref)
 Initiate subscription. More...
 
subscription_bind_t so_subscribe_self ()
 Initiate subscription to agent's direct mbox. More...
 
void so_create_event_subscription (const mbox_t &mbox_ref, std::type_index type_index, const state_t &target_state, const event_handler_method_t &method, thread_safety_t thread_safety, event_handler_kind_t handler_kind)
 Create a subscription for an event. More...
 
void so_destroy_event_subscription (const mbox_t &mbox, const std::type_index &subscription_type, const state_t &target_state)
 Destroy event subscription. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer >::value, void >::type so_drop_subscription (const mbox_t &mbox, const state_t &target_state, Method_Pointer)
 Drop subscription for the state specified. More...
 
template<class Message >
void so_drop_subscription (const mbox_t &mbox, const state_t &target_state)
 Drop subscription for the state specified. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer >::value, void >::type so_drop_subscription (const mbox_t &mbox, Method_Pointer)
 Drop subscription for the default agent state. More...
 
template<class Message >
void so_drop_subscription (const mbox_t &mbox)
 Drop subscription for the default agent state. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer >::value, void >::type so_drop_subscription_for_all_states (const mbox_t &mbox, Method_Pointer)
 Drop subscription for all states. More...
 
template<class Message >
void so_drop_subscription_for_all_states (const mbox_t &mbox)
 Drop subscription for all states. More...
 
template<class Message >
bool so_has_subscription (const mbox_t &mbox, const state_t &target_state) const noexcept
 Check the presence of a subscription. More...
 
template<class Message >
bool so_has_subscription (const mbox_t &mbox) const noexcept
 Check the presence of a subscription in the default_state. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer >::value, bool >::type so_has_subscription (const mbox_t &mbox, const state_t &target_state, Method_Pointer) const noexcept
 Check the presence of a subscription. More...
 
template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer >::value, bool >::type so_has_subscription (const mbox_t &mbox, Method_Pointer) const noexcept
 Check the presence of a subscription. More...
 
Methods for dealing with deadletter subscriptions.
void so_create_deadletter_subscription (const mbox_t &mbox, const std::type_index &msg_type, const event_handler_method_t &method, thread_safety_t thread_safety)
 Create a subscription for a deadletter handler. More...
 
void so_destroy_deadletter_subscription (const mbox_t &mbox, const std::type_index &msg_type)
 Destroy a subscription for a deadletter handler. More...
 
template<typename Event_Handler >
void so_subscribe_deadletter_handler (const so_5::mbox_t &mbox, Event_Handler &&handler, thread_safety_t thread_safety=thread_safety_t::unsafe)
 Create a subscription for deadletter handler for a specific message from a specific mbox. More...
 
template<typename Message >
void so_drop_deadletter_handler (const so_5::mbox_t &mbox)
 Drops the subscription for deadletter handler. More...
 
template<typename Message >
bool so_has_deadletter_handler (const so_5::mbox_t &mbox) const noexcept
 Checks the presence of deadletter handler for a message of a specific type from a specific mbox. More...
 
Methods for dealing with message delivery filters.
template<typename Message >
void so_set_delivery_filter (const mbox_t &mbox, delivery_filter_unique_ptr_t filter)
 Set a delivery filter. More...
 
template<typename Lambda >
void so_set_delivery_filter (const mbox_t &mbox, Lambda &&lambda)
 Set a delivery filter. More...
 
template<typename Lambda >
void so_set_delivery_filter_for_mutable_msg (const mbox_t &mbox, Lambda &&lambda)
 Set a delivery filter for a mutable message. More...
 
template<typename Message >
void so_drop_delivery_filter (const mbox_t &mbox) noexcept
 Drop a delivery filter. More...
 
Dealing with priority.
priority_t so_priority () const
 Get the priority of the agent. More...
 

Static Public Member Functions

static void call_push_event (agent_t &agent, const message_limit::control_block_t *limit, mbox_id_t mbox_id, std::type_index msg_type, const message_ref_t &message)
 Push an event to the agent's event queue. More...
 
static agent_tuning_options_t tuning_options ()
 Create tuning options object with default values. More...
 
template<typename Lambda >
static custom_direct_mbox_factory_t custom_direct_mbox_factory (Lambda &&lambda)
 Helper for creation a custom direct mbox factory. More...
 
static execution_hint_t so_create_execution_hint (execution_demand_t &demand)
 Create execution hint for the specified demand. More...
 
- Static Public Member Functions inherited from so_5::message_limit::message_limit_methods_mixin_t
template<typename Msg >
static drop_indicator_t< Msg > limit_then_drop (unsigned int limit)
 A helper function for creating drop_indicator. More...
 
template<typename Msg >
static abort_app_indicator_t< Msg > limit_then_abort (unsigned int limit)
 A helper function for creating abort_app_indicator. More...
 
template<typename M , typename L >
static log_then_abort_app_indicator_t< M, L > limit_then_abort (unsigned int limit, L lambda)
 A helper function for creating log_then_abort_app_indicator. More...
 
template<typename Msg , typename Lambda >
static redirect_indicator_t< Msg, Lambda > limit_then_redirect (unsigned int limit, Lambda dest_getter)
 A helper function for creating redirect_indicator. More...
 
template<typename Msg >
static auto limit_then_redirect (unsigned int limit, mbox_t destination)
 A helper function for creating redirect_indicator. More...
 
template<typename Lambda , typename Arg = typename so_5::details::lambda_traits:: argument_type_if_lambda< Lambda >::type>
static transform_indicator_t< Arg > limit_then_transform (unsigned int limit, Lambda transformator)
 A helper function for creating transform_indicator. More...
 
template<typename Source , typename Lambda >
static transform_indicator_t< Source > limit_then_transform (unsigned int limit, Lambda transformator)
 A helper function for creating transform_indicator. More...
 
template<typename Msg , typename... Args>
static transformed_message_t< Msg > make_transformed (mbox_t mbox, Args &&... args)
 Helper method for creating message transformation result. More...
 

Static Public Attributes

static constexpr const state_t::history_t shallow_history
 Short alias for so_5::state_t::history_t::shallow. More...
 
static constexpr const state_t::history_t deep_history
 Short alias for so_5::state_t::history_t::deep. More...
 

Protected Member Functions

Accessing the default state.
const state_tso_default_state () const
 Access to the agent's default state. More...
 
Agent initialization methods.
void so_initiate_agent_definition ()
 A correct initiation of so_define_agent method call. More...
 
virtual void so_define_agent ()
 Hook on define agent for SObjectizer. More...
 
bool so_was_defined () const
 Is method define_agent already called? More...
 

Private Types

enum  agent_status_t : char { agent_status_t::not_defined_yet, agent_status_t::defined, agent_status_t::state_switch_in_progress }
 Enumeration of possible agent statuses. More...
 
using handler_finder_t = const impl::event_handler_data_t *(*)(execution_demand_t &, const char *)
 Type of function for searching event handler. More...
 

Private Member Functions

void destroy_all_subscriptions_and_filters () noexcept
 Destroy all agent's subscriptions. More...
 
agent_ref_t create_ref ()
 Make an agent reference. More...
 
void ensure_operation_is_on_working_thread (const char *operation_name) const
 Enables operation only if it is performed on agent's working thread. More...
 
void drop_all_delivery_filters () noexcept
 Drops all delivery filters. More...
 
void do_set_delivery_filter (const mbox_t &mbox, const std::type_index &msg_type, delivery_filter_unique_ptr_t filter)
 Set a delivery filter. More...
 
void do_drop_delivery_filter (const mbox_t &mbox, const std::type_index &msg_type) noexcept
 Drop a delivery filter. More...
 
void do_change_agent_state (const state_t &state_to_be_set)
 Perform actual operations related to state switch. More...
 
void do_state_switch (const state_t &state_to_be_set) noexcept
 Actual action for switching agent state. More...
 
void return_to_default_state_if_possible () noexcept
 Return agent to the default state. More...
 
bool is_agent_deactivated () const noexcept
 Is agent already deactivated. More...
 
Embedding agent into the SObjectizer Run-time.
void bind_to_coop (coop_t &coop)
 Bind agent to the cooperation. More...
 
void shutdown_agent () noexcept
 Agent shutdown deriver. More...
 
Subscription/unsubscription implementation details.
const message_limit::control_block_tdetect_limit_for_message_type (const std::type_index &msg_type)
 Detect limit for that message type. More...
 
void do_drop_subscription (const mbox_t &mbox, const std::type_index &msg_type, const state_t &target_state)
 Remove subscription for the state specified. More...
 
void do_drop_subscription_for_all_states (const mbox_t &mbox, const std::type_index &msg_type)
 Remove subscription for all states. More...
 
bool do_check_subscription_presence (const mbox_t &mbox, const std::type_index &msg_type, const state_t &target_state) const noexcept
 Check the presence of a subscription. More...
 
bool do_check_deadletter_presence (const mbox_t &mbox, const std::type_index &msg_type) const noexcept
 Check the presence of a deadletter handler. More...
 
Event handling implementation details.
void push_event (const message_limit::control_block_t *limit, mbox_id_t mbox_id, std::type_index msg_type, const message_ref_t &message)
 Push event into the event queue. More...
 
- Private Member Functions inherited from so_5::atomic_refcounted_t
 atomic_refcounted_t (const atomic_refcounted_t &)=delete
 
atomic_refcounted_toperator= (const atomic_refcounted_t &)=delete
 
 atomic_refcounted_t () noexcept
 Default constructor. More...
 
 ~atomic_refcounted_t () noexcept=default
 Destructor. More...
 
void inc_ref_count () noexcept
 Increments reference count. More...
 
unsigned long dec_ref_count () noexcept
 Decrement reference count. More...
 

Static Private Member Functions

static void process_message (current_thread_id_t working_thread_id, execution_demand_t &d, thread_safety_t thread_safety, event_handler_method_t method)
 Actual implementation of message handling. More...
 
static void process_enveloped_msg (current_thread_id_t working_thread_id, execution_demand_t &d, const impl::event_handler_data_t *handler_data)
 Actual implementation of enveloped message handling. More...
 
static const impl::event_handler_data_thandler_finder_msg_tracing_disabled (execution_demand_t &demand, const char *context_marker)
 Handler finder for the case when message delivery tracing is disabled. More...
 
static const impl::event_handler_data_thandler_finder_msg_tracing_enabled (execution_demand_t &demand, const char *context_marker)
 Handler finder for the case when message delivery tracing is enabled. More...
 
static const impl::event_handler_data_tfind_event_handler_for_current_state (execution_demand_t &demand)
 Actual search for event handler with respect to parent-child relationship between agent states. More...
 
static const impl::event_handler_data_tfind_deadletter_handler (execution_demand_t &demand)
 Search for event handler between deadletter handlers. More...
 

Private Attributes

const state_t st_default { self_ptr(), "<DEFAULT>" }
 
const state_tm_current_state_ptr
 Current agent state. More...
 
agent_status_t m_current_status
 Current agent status. More...
 
impl::state_listener_controller_t m_state_listener_controller
 State listeners controller. More...
 
handler_finder_t m_handler_finder
 Function for searching event handler. More...
 
impl::subscription_storage_unique_ptr_t m_subscriptions
 All agent's subscriptions. More...
 
std::unique_ptr< message_limit::impl::info_storage_tm_message_limits
 Run-time information for message limits. More...
 
environment_tm_env
 SObjectizer Environment for which the agent is belong. More...
 
default_rw_spinlock_t m_event_queue_lock
 Event queue operation protector. More...
 
event_queue_tm_event_queue
 A pointer to event_queue. More...
 
const mbox_t m_direct_mbox
 A direct mbox for the agent. More...
 
so_5::current_thread_id_t m_working_thread_id
 Working thread id. More...
 
coop_tm_agent_coop
 Agent is belong to this cooperation. More...
 
std::unique_ptr< impl::delivery_filter_storage_tm_delivery_filters
 Delivery filters for that agents. More...
 
const priority_t m_priority
 Priority of the agent. More...
 

Friends

class subscription_bind_t
 
class state_t
 
class so_5::impl::mpsc_mbox_t
 
class so_5::impl::state_switch_guard_t
 
class so_5::impl::internal_agent_iface_t
 
class so_5::enveloped_msg::impl::agent_demand_handler_invoker_t
 
template<typename T >
class intrusive_ptr_t
 

Demand handlers.

void ensure_binding_finished ()
 Ensures that all agents from cooperation are bound to dispatchers. More...
 
static void demand_handler_on_start (current_thread_id_t working_thread_id, execution_demand_t &d)
 Calls so_evt_start method for agent. More...
 
static demand_handler_pfn_t get_demand_handler_on_start_ptr () noexcept
 
static void demand_handler_on_finish (current_thread_id_t working_thread_id, execution_demand_t &d)
 Calls so_evt_finish method for agent. More...
 
static demand_handler_pfn_t get_demand_handler_on_finish_ptr () noexcept
 
static void demand_handler_on_message (current_thread_id_t working_thread_id, execution_demand_t &d)
 Calls event handler for message. More...
 
static demand_handler_pfn_t get_demand_handler_on_message_ptr () noexcept
 
static void demand_handler_on_enveloped_msg (current_thread_id_t working_thread_id, execution_demand_t &d)
 Handles the enveloped message. More...
 
static demand_handler_pfn_t get_demand_handler_on_enveloped_msg_ptr () noexcept
 

Detailed Description

A base class for agents.

An agent in SObjctizer must be derived from the agent_t.

The base class provides various methods whose can be splitted into the following groups:

Methods for the interaction with SObjectizer

Method so_5::agent_t::so_environment() serves for the access to the SObjectizer Environment (and, therefore, to all methods of the SObjectizer Environment). This method could be called immediatelly after the agent creation. This is because agent is bound to the SObjectizer Environment during the creation process.

Hook methods

The base class defines several hook-methods. Its default implementation do nothing.

The method agent_t::so_define_agent() is called just before agent will started by SObjectizer as a part of the agent registration process. It should be reimplemented for the initial subscription of the agent to messages.

There are two hook-methods related to important agent's lifetime events: agent_t::so_evt_start() and agent_t::so_evt_finish(). They are called by SObjectizer in next circumstances:

Methods so_evt_start() and so_evt_finish() are called by SObjectizer and user can just reimplement them to implement the agent-specific logic.

Message subscription and unsubscription methods

Any method with one of the following prototypes can be used as an event handler:

return_type evt_handler( mhood_t< Message > msg );
return_type evt_handler( const mhood_t< Message > & msg );
return_type evt_handler( const Message & msg );
return_type evt_handler( Message msg );
// Since v.5.5.20:
return_type evt_handler( mhood_t< Message > msg ) const;
return_type evt_handler( const mhood_t< Message > & msg ) const;
return_type evt_handler( const Message & msg ) const;
return_type evt_handler( Message msg ) const;

Where evt_handler is a name of the event handler, Message is a message type.

The class mhood_t is a wrapper on pointer to an instance of the Message. It is very similar to std::unique_ptr. The pointer to Message can be a nullptr. It happens in case when the message has no actual data and servers just a signal about something.

Please note that handlers with the following prototypes can be used only for messages, not signals:

return_type evt_handler( const Message & msg );
return_type evt_handler( Message msg );
// Since v.5.5.20:
return_type evt_handler( const Message & msg ) const;
return_type evt_handler( Message msg ) const;

A subscription to the message is performed by the methods so_subscribe() and so_subscribe_self(). This method returns an instance of the so_5::subscription_bind_t which does all actual actions of the subscription process. This instance already knows agents and message mbox and uses the default agent state for the event subscription (binding to different state is also possible).

The presence of a subscription can be checked by so_has_subscription() method.

A subscription can be dropped (removed) by so_drop_subscription() and so_drop_subscription_for_all_states() methods.

Deadletter handlers subscription and unsubscription

Since v.5.5.21 SObjectizer supports deadletter handlers. Such handlers are called if there is no any ordinary event handler for a specific messages from a specific mbox.

Deadletter handler can be implemented by an agent method or by lambda function. Deadletter handler can have one of the following formats:

void evt_handler( mhood_t< Message > msg );
void return_type evt_handler( mhood_t< Message > msg ) const;
void return_type evt_handler( const mhood_t< Message > & msg );
void return_type evt_handler( const mhood_t< Message > & msg ) const;
void return_type evt_handler( const Message & msg );
void return_type evt_handler( const Message & msg ) const;
void return_type evt_handler( Message msg );
void return_type evt_handler( Message msg ) const;

Subscription for a deadletter handler can be created by so_subscribe_deadletter_handler() method.

The presence of a deadletter handler can be checked by so_has_deadletter_handler() method.

A deadletter can be dropped (removed) by so_drop_deadletter_handler() and so_drop_subscription_for_all_states() methods.

Methods for working with an agent state

The agent can change its state by his so_change_state() method.

An attempt to switch an agent to the state which belongs to the another agent is an error. If state is belong to the same agent there are no possibility to any run-time errors. In this case changing agent state is a very safe operation.

In some cases it is necessary to detect agent state switching. For example for application monitoring purposes. This can be done by "state listeners".

Any count of state listeners can be set for an agent. There are two methods for that:

Work thread identification

Since v.5.4.0 some operations for agent are enabled only on agent's work thread. They are:

Work thread for an agent is defined as follows:

Note
Some dispatchers could provide several work threads for an agent. In such case there would not be work thread id. And operations like changing agent state or creation of subscription would be prohibited after agent registration.
Examples:
so_5/adv_thread_pool_fifo/main.cpp, so_5/blinking_led/main.cpp, so_5/chameneos_prealloc_msgs/main.cpp, so_5/chameneos_simple/main.cpp, so_5/chstate/main.cpp, so_5/chstate_msg_tracing/main.cpp, so_5/coop_listener/main.cpp, so_5/coop_notification/main.cpp, so_5/coop_user_resources/main.cpp, so_5/custom_direct_mbox/main.cpp, so_5/custom_error_logger/main.cpp, so_5/custom_work_thread_factory/main.cpp, so_5/deadletter_handler/main.cpp, so_5/default_message_limits/main.cpp, so_5/delivery_filters/main.cpp, so_5/disp/main.cpp, so_5/dispatcher_for_children/main.cpp, so_5/dispatcher_hello/main.cpp, so_5/dispatcher_restarts/main.cpp, so_5/exception_logger/main.cpp, so_5/exception_reaction/main.cpp, so_5/hardwork_imit/main.cpp, so_5/hello_all/main.cpp, so_5/hello_delay/main.cpp, so_5/hello_evt_handler/main.cpp, so_5/hello_evt_lambda/main.cpp, so_5/hello_periodic/main.cpp, so_5/hello_world/main.cpp, so_5/hello_world_simple_not_mtsafe/main.cpp, so_5/intercom_statechart/main.cpp, so_5/machine_control/main.cpp, so_5/make_agent_ref/main.cpp, so_5/make_new_direct_mbox/main.cpp, so_5/make_pipeline/main.cpp, so_5/many_timers/main.cpp, so_5/modify_resend_as_immutable/main.cpp, so_5/mutable_msg_agents/main.cpp, so_5/named_dispatchers_layer/main.cpp, so_5/news_board/main.cpp, so_5/nohandler_msg_tracing/main.cpp, so_5/parent_coop/main.cpp, so_5/ping_pong/main.cpp, so_5/ping_pong_minimal/main.cpp, so_5/ping_pong_with_owner/main.cpp, so_5/prio_work_stealing/main.cpp, so_5/producer_consumer_mchain/main.cpp, so_5/queue_size_stats/main.cpp, so_5/redirect_and_transform/main.cpp, so_5/selective_msg_tracing/main.cpp, so_5/simple_message_deadline/main.cpp, so_5/state_deep_history/main.cpp, so_5/stop_guard/main.cpp, so_5/subscriptions/main.cpp, so_5/two_handlers/main.cpp, and so_5/wrapped_env_demo_2/main.cpp.

Member Typedef Documentation

◆ context_t

Short alias for agent_context.

Since
v.5.5.4

◆ handler_finder_t

using so_5::agent_t::handler_finder_t = const impl::event_handler_data_t *(*)( execution_demand_t & , const char * )
private

Type of function for searching event handler.

Since
v.5.5.9

◆ initial_substate_of

Short alias for so_5::initial_substate_of.

Since
v.5.5.15

◆ mhood_t

template<typename T >
using so_5::agent_t::mhood_t = so_5::mhood_t< T >

Short alias for so_5::mhood_t.

Since
v.5.5.14

◆ mutable_mhood_t

template<typename T >
using so_5::agent_t::mutable_mhood_t = so_5::mutable_mhood_t< T >

Short alias for so_5::mutable_mhood_t.

Since
v.5.5.19

◆ state_t

Short alias for so_5::state_t.

Since
v.5.5.13

◆ substate_of

Short alias for so_5::substate_of.

Since
v.5.5.15

Member Enumeration Documentation

◆ agent_status_t

enum so_5::agent_t::agent_status_t : char
strongprivate

Enumeration of possible agent statuses.

Since
v.5.5.18
Enumerator
not_defined_yet 

Agent is not defined yet. This is an initial agent status.

defined 

Agent is defined.

state_switch_in_progress 

State switch operation is in progress.

Constructor & Destructor Documentation

◆ agent_t() [1/3]

so_5::agent_t::agent_t ( environment_t env)
explicit

Constructor.

Agent must be bound to the SObjectizer Environment during its creation. And that binding cannot be changed anymore.

Parameters
envThe Environment for this agent must exist.
Examples:
so_5/coop_listener/main.cpp, so_5/hardwork_imit/main.cpp, so_5/hello_delay/main.cpp, so_5/hello_evt_handler/main.cpp, so_5/hello_evt_lambda/main.cpp, so_5/hello_periodic/main.cpp, so_5/hello_world/main.cpp, so_5/make_new_direct_mbox/main.cpp, so_5/news_board/main.cpp, so_5/parent_coop/main.cpp, and so_5/producer_consumer_mchain/main.cpp.

◆ agent_t() [2/3]

so_5::agent_t::agent_t ( environment_t env,
agent_tuning_options_t  tuning_options 
)

Constructor which allows specification of agent's tuning options.

Since
v.5.5.3
Usage sample:
using namespace so_5;
class my_agent : public agent_t
{
public :
my_agent( environment_t & env )
.subscription_storage_factory(
{...}
}

◆ agent_t() [3/3]

so_5::agent_t::agent_t ( context_t  ctx)
explicit

Constructor which simplifies agent construction with or without agent's tuning options.

Since
v.5.5.4
Usage sample:
class my_agent : public so_5::agent_t
{
public :
my_agent( context_t ctx )
: so_5::agent( ctx + limit_then_drop< get_status >(1) )
{}
...
};
class my_more_specific_agent : public my_agent
{
public :
my_more_specific_agent( context_t ctx )
: my_agent( ctx + limit_then_drop< reconfigure >(1) )
{}
};
// Then somewhere in the code:
auto coop = env.make_coop();
auto a = coop->make_agent< my_agent >();
auto b = coop->make_agent< my_more_specific_agent >();

◆ ~agent_t()

so_5::agent_t::~agent_t ( )
virtual

Member Function Documentation

◆ bind_to_coop()

void so_5::agent_t::bind_to_coop ( coop_t coop)
private

Bind agent to the cooperation.

Initializes an internal cooperation pointer.

Parameters
coopCooperation for that agent.

◆ call_push_event()

static void so_5::agent_t::call_push_event ( agent_t agent,
const message_limit::control_block_t limit,
mbox_id_t  mbox_id,
std::type_index  msg_type,
const message_ref_t message 
)
inlinestatic

Push an event to the agent's event queue.

This method is used by SObjectizer for the agent's event scheduling.

◆ create_ref()

agent_ref_t so_5::agent_t::create_ref ( )
private

Make an agent reference.

This is an internal SObjectizer method. It is called when it is guaranteed that the agent is still necessary and something has reference to it.

◆ custom_direct_mbox_factory()

template<typename Lambda >
static custom_direct_mbox_factory_t so_5::agent_t::custom_direct_mbox_factory ( Lambda &&  lambda)
inlinestatic

Helper for creation a custom direct mbox factory.

Usage example:

class my_agent : public so_5::agent_t {
...
public:
my_agent( context_t ctx )
so_5::mbox_t actual_mbox )
{
return so_5::mbox_t{ new my_custom_mbox{ agent_ptr.ptr(), std::move(actual_mbox) } };
} )
}
{...}
...
};
Since
v.5.7.4
Examples:
so_5/custom_direct_mbox/main.cpp.

◆ demand_handler_on_enveloped_msg()

void so_5::agent_t::demand_handler_on_enveloped_msg ( current_thread_id_t  working_thread_id,
execution_demand_t d 
)
static

Handles the enveloped message.

Since
v.5.5.23

◆ demand_handler_on_finish()

void so_5::agent_t::demand_handler_on_finish ( current_thread_id_t  working_thread_id,
execution_demand_t d 
)
static

Calls so_evt_finish method for agent.

Since
v.5.2.0

◆ demand_handler_on_message()

void so_5::agent_t::demand_handler_on_message ( current_thread_id_t  working_thread_id,
execution_demand_t d 
)
static

Calls event handler for message.

Since
v.5.2.0

◆ demand_handler_on_start()

void so_5::agent_t::demand_handler_on_start ( current_thread_id_t  working_thread_id,
execution_demand_t d 
)
static

Calls so_evt_start method for agent.

Since
v.5.2.0

◆ destroy_all_subscriptions_and_filters()

void so_5::agent_t::destroy_all_subscriptions_and_filters ( )
privatenoexcept

Destroy all agent's subscriptions.

Note
This method is intended to be used in the destructor and methods like so_deactivate_agent().
Attention
It's noexcept method because there is no way to recover in case when deletion of subscriptions throws.
Since
v.5.7.3

◆ detect_limit_for_message_type()

const message_limit::control_block_t * so_5::agent_t::detect_limit_for_message_type ( const std::type_index &  msg_type)
private

Detect limit for that message type.

Since
v.5.5.4
Note
Since v.5.7.1 it isn't a const method.
Returns
nullptr if message limits are not used.
Exceptions
exception_tif message limits are used but the limit for that message type is not found.

◆ do_change_agent_state()

void so_5::agent_t::do_change_agent_state ( const state_t state_to_be_set)
private

Perform actual operations related to state switch.

It throws if the agent in awaiting_deregistration_state and state_to_be_set isn't awaiting_deregistration_state.

Note
This method doesn't check the working context. It's assumed that this check has already been performed by caller.
Since
v.5.7.3
Parameters
state_to_be_setNew state to be set as the current state.

◆ do_check_deadletter_presence()

bool so_5::agent_t::do_check_deadletter_presence ( const mbox_t mbox,
const std::type_index &  msg_type 
) const
privatenoexcept

Check the presence of a deadletter handler.

Since
v.5.5.21
Parameters
mboxMessage's mbox.
msg_typeMessage type.

◆ do_check_subscription_presence()

bool so_5::agent_t::do_check_subscription_presence ( const mbox_t mbox,
const std::type_index &  msg_type,
const state_t target_state 
) const
privatenoexcept

Check the presence of a subscription.

Since
v.5.5.19.5
Parameters
mboxMessage's mbox.
msg_typeMessage type.
target_stateState for the subscription.

◆ do_drop_delivery_filter()

void so_5::agent_t::do_drop_delivery_filter ( const mbox_t mbox,
const std::type_index &  msg_type 
)
privatenoexcept

Drop a delivery filter.

Since
v.5.5.5

◆ do_drop_subscription()

void so_5::agent_t::do_drop_subscription ( const mbox_t mbox,
const std::type_index &  msg_type,
const state_t target_state 
)
private

Remove subscription for the state specified.

Since
v.5.2.3
Parameters
mboxMessage's mbox.
msg_typeMessage type.
target_stateState for event.

◆ do_drop_subscription_for_all_states()

void so_5::agent_t::do_drop_subscription_for_all_states ( const mbox_t mbox,
const std::type_index &  msg_type 
)
private

Remove subscription for all states.

Since
v.5.2.3
Parameters
mboxMessage's mbox.
msg_typeMessage type.

◆ do_set_delivery_filter()

void so_5::agent_t::do_set_delivery_filter ( const mbox_t mbox,
const std::type_index &  msg_type,
delivery_filter_unique_ptr_t  filter 
)
private

Set a delivery filter.

Since
v.5.5.5

◆ do_state_switch()

void so_5::agent_t::do_state_switch ( const state_t state_to_be_set)
privatenoexcept

Actual action for switching agent state.

Since
v.5.5.15
Parameters
state_to_be_setNew state to be set as the current state.

◆ drop_all_delivery_filters()

void so_5::agent_t::drop_all_delivery_filters ( )
privatenoexcept

Drops all delivery filters.

Since
v.5.5.0

◆ ensure_binding_finished()

void so_5::agent_t::ensure_binding_finished ( )

Ensures that all agents from cooperation are bound to dispatchers.

Since
v.5.5.8

◆ ensure_operation_is_on_working_thread()

void so_5::agent_t::ensure_operation_is_on_working_thread ( const char *  operation_name) const
private

Enables operation only if it is performed on agent's working thread.

Since
v.5.4.0

◆ find_deadletter_handler()

const impl::event_handler_data_t * so_5::agent_t::find_deadletter_handler ( execution_demand_t demand)
staticprivate

Search for event handler between deadletter handlers.

Returns
nullptr if event handler is not found.
Since
v.5.5.21

◆ find_event_handler_for_current_state()

const impl::event_handler_data_t * so_5::agent_t::find_event_handler_for_current_state ( execution_demand_t demand)
staticprivate

Actual search for event handler with respect to parent-child relationship between agent states.

Since
v.5.5.15

◆ get_demand_handler_on_enveloped_msg_ptr()

demand_handler_pfn_t so_5::agent_t::get_demand_handler_on_enveloped_msg_ptr ( )
staticnoexcept
Since
v.5.5.24

◆ get_demand_handler_on_finish_ptr()

demand_handler_pfn_t so_5::agent_t::get_demand_handler_on_finish_ptr ( )
staticnoexcept
Since
v.5.4.0
Note
This method is necessary for GCC on Cygwin.

◆ get_demand_handler_on_message_ptr()

demand_handler_pfn_t so_5::agent_t::get_demand_handler_on_message_ptr ( )
staticnoexcept
Since
v.5.4.0
Note
This method is necessary for GCC on Cygwin.

◆ get_demand_handler_on_start_ptr()

demand_handler_pfn_t so_5::agent_t::get_demand_handler_on_start_ptr ( )
staticnoexcept
Since
v.5.4.0
Note
This method is necessary for GCC on Cygwin.

◆ handler_finder_msg_tracing_disabled()

const impl::event_handler_data_t * so_5::agent_t::handler_finder_msg_tracing_disabled ( execution_demand_t demand,
const char *  context_marker 
)
staticprivate

Handler finder for the case when message delivery tracing is disabled.

Since
v.5.5.9

◆ handler_finder_msg_tracing_enabled()

const impl::event_handler_data_t * so_5::agent_t::handler_finder_msg_tracing_enabled ( execution_demand_t demand,
const char *  context_marker 
)
staticprivate

Handler finder for the case when message delivery tracing is enabled.

Since
v.5.5.9

◆ is_agent_deactivated()

bool so_5::agent_t::is_agent_deactivated ( ) const
privatenoexcept

Is agent already deactivated.

Deactivated agent is in awaiting_deregistration_state. This method checks that the current state of the agent is awaiting_deregistration_state.

Attention
This method isn't thread safe and should be used with care. A caller should guarantee that it's called from the right working thread.
Since
v.5.7.3

◆ process_enveloped_msg()

void so_5::agent_t::process_enveloped_msg ( current_thread_id_t  working_thread_id,
execution_demand_t d,
const impl::event_handler_data_t handler_data 
)
staticprivate

Actual implementation of enveloped message handling.

Note
handler_data can be nullptr. It means that an event handler for that message type if not found and special hook will be called for the envelope.
Since
v.5.5.23

◆ process_message()

void so_5::agent_t::process_message ( current_thread_id_t  working_thread_id,
execution_demand_t d,
thread_safety_t  thread_safety,
event_handler_method_t  method 
)
staticprivate

Actual implementation of message handling.

Since
v.5.4.0
Note
Since v.5.5.17.1 argument method is passed as copy. It prevents deallocation of event_handler_method in the following case:
so_subscribe( mbox ).event< some_signal >( [this, mbox] {
so_drop_subscription< some_signal >( mbox );
... // Some other actions.
} );
Attention
Implementation notes: it's important that method is passed by value. It's because subscription can be deleted during the work of process_message (due to unsubscription inside the event handler) and if pass method by a reference then that reference can become invalid.

◆ push_event()

void so_5::agent_t::push_event ( const message_limit::control_block_t limit,
mbox_id_t  mbox_id,
std::type_index  msg_type,
const message_ref_t message 
)
private

Push event into the event queue.

Parameters
limitOptional message limit.
mbox_idID of mbox for this event.
msg_typeMessage type for event.
messageEvent message.

◆ return_to_default_state_if_possible()

void so_5::agent_t::return_to_default_state_if_possible ( )
privatenoexcept

Return agent to the default state.

Since
v.5.5.15
Note
This method is called just before invocation of so_evt_finish() to return agent to the default state. This return will initiate invocation of on_exit handlers for all active states of the agent.
Attention
State switch is not performed if agent is already in default state or if it waits deregistration after unhandled exception.

◆ self_ptr() [1/2]

const agent_t* so_5::agent_t::self_ptr ( ) const
inline

Get the raw pointer of itself.

This method is intended for use in the member initialization list instead 'this' to suppres compiler warnings. For example for an agent state initialization:

class a_sample_t : public so_5::agent_t
{
typedef so_5::agent_t base_type_t;
// Agent state.
const so_5::state_t m_sample_state;
public:
a_sample_t( so_5::environment_t & env )
:
base_type_t( env ),
m_sample_state( self_ptr() )
{
// ...
}
// ...
};

◆ self_ptr() [2/2]

agent_t* so_5::agent_t::self_ptr ( )
inline

◆ shutdown_agent()

void so_5::agent_t::shutdown_agent ( )
privatenoexcept

Agent shutdown deriver.

Since
v.5.2.3

Method destroys all agent subscriptions.

◆ so_add_destroyable_listener()

void so_5::agent_t::so_add_destroyable_listener ( agent_state_listener_unique_ptr_t  state_listener)

Add a state listener to the agent.

Agent takes care of the state_listener destruction.

◆ so_add_nondestroyable_listener()

void so_5::agent_t::so_add_nondestroyable_listener ( agent_state_listener_t state_listener)

Add a state listener to the agent.

A programmer should guarantee that the lifetime of state_listener is exceeds lifetime of the agent.

◆ so_bind_to_dispatcher()

void so_5::agent_t::so_bind_to_dispatcher ( event_queue_t queue)
noexcept

Binding agent to the dispatcher.

Since
v.5.4.0

This is an actual start of agent's work in SObjectizer.

Note
This method was a de-facto noexcept in previous versions of SObjectizer. But didn't marked as noexcept because of need of support old C++ compilers. Since v.5.6.0 it is officially noexcept.
Parameters
queueActual event queue for an agent.

◆ so_change_state()

void so_5::agent_t::so_change_state ( const state_t new_state)

Change the current state of the agent.

Usage sample:

void a_sample_t::evt_smth( mhood_t< message_one_t > msg )
{
// If something wrong with the message then we should
// switch to the error_state.
if( error_in_data( *msg ) )
so_change_state( m_error_state );
}
Attention
This method has to be called from a worker thread assigned to the agent by the dispatcher. This method can't be called from thread_safe event-handlers because so_change_state() modifies the state of the agent.
Parameters
new_stateNew agent state.

◆ so_coop()

coop_handle_t so_5::agent_t::so_coop ( ) const

Get a handle of agent's coop.

Note
This method is a replacement for so_coop_name() method from previous versions of SObjectizer-5.
Attention
If this method is called when agent is not registered (e.g. there is no coop for agent) then this method will throw.

Usage example:

class parent final : public so_5::agent_t {
...
void so_evt_start() override {
// Create a child coop.
auto coop = so_environment().make_coop(
// We as a parent coop.
so_coop() );
...; // Fill the coop.
so_environment().register_coop( std::move(coop) );
}
};
Since
v.5.6.0

◆ so_create_deadletter_subscription()

void so_5::agent_t::so_create_deadletter_subscription ( const mbox_t mbox,
const std::type_index &  msg_type,
const event_handler_method_t method,
thread_safety_t  thread_safety 
)

Create a subscription for a deadletter handler.

Note
This is low-level method intended to be used by libraries writters. Do not call it directly if you don't understand its purpose and what its arguments mean. Use so_subscribe_deadletter_handler() instead.

This method actually creates a subscription to deadletter handler for messages/signal of type msg_type from mbox mbox.

Exceptions
so_5::exception_tin the case when the subscription of a deadletter handler for type msg_type from mbox is already exists.
Since
v.5.5.21
Parameters
mboxMessage's mbox.
msg_typeMessage type.
methodEvent handler caller.
thread_safetyThread safety of the event handler.

◆ so_create_event_subscription()

void so_5::agent_t::so_create_event_subscription ( const mbox_t mbox_ref,
std::type_index  type_index,
const state_t target_state,
const event_handler_method_t method,
thread_safety_t  thread_safety,
event_handler_kind_t  handler_kind 
)

Create a subscription for an event.

Note
Before v.5.5.21 it was a private method. Since v.5.5.21 it is a public method with a standard so_-prefix. It was made public to allow creation of subscriptions to agent from outside of agent.
Parameter handler_kind was introduced in v.5.7.0.
Parameters
mbox_refMessage's mbox.
type_indexMessage type.
target_stateState for event.
methodEvent handler caller.
thread_safetyThread safety of the event handler.
handler_kindKind of that event handler.

◆ so_create_execution_hint()

execution_hint_t so_5::agent_t::so_create_execution_hint ( execution_demand_t demand)
static

Create execution hint for the specified demand.

Since
v.5.4.0

The hint returned is intendent for the immediately usage. It must not be stored for the long time and used sometime in the future. It is because internal state of the agent can be changed and some references from hint object to agent's internals become invalid.

Parameters
demandDemand for execution of event handler.

◆ so_current_state()

const state_t& so_5::agent_t::so_current_state ( ) const
inline

Access to the current agent state.

Note
There is a change in behaviour of this methon in v.5.5.22. If some on_enter/on_exit handler calls this method during the state change procedure this method will return the state for which this on_enter/on_exit handler is called. For example:
class demo final : public so_5::agent_t {
state_t st_1{ this };
state_t st_1_1{ initial_substate_of{st_1} };
state_t st_1_2{ substate_of{st_1}};
...
virtual void so_define_agent() override {
st_1.on_enter([this]{
assert(st_1 == so_current_state());
...
});
st_1_1.on_enter([this]{
assert(st_1_1 == so_current_state());
...
});
...
}
};

◆ so_deactivate_agent()

void so_5::agent_t::so_deactivate_agent ( )

Deactivate the agent.

This method deactivates the agent:

  • drops all agent's subscriptions (including deadletter handlers) and delivery filters;
  • switches the agent to a special state in that the agent does nothing and just waits the deregistration.

Sometimes it is necessary to mark an agent as 'failed'. Such an agent shouldn't process anything and the only thing that is allowed is waiting for the deregistration. For example:

class some_agent final : public so_5::agent_t
{
state_t st_working{ this, "working" };
state_t st_failed{ this, "failed" };
...
void on_enter_st_failed()
{
// Notify some supervisor about the failure.
// It will deregister the whole cooperation with failed agent.
so_5::send<msg_failure>( supervisor_mbox(), ... );
}
...
void so_define_agent() override
{
this >>= st_working;
st_failed.on_enter( &some_agent::on_enter_st_failed );
...
}
void evt_some_event(mhood_t<some_msg> cmd)
{
try
{
do_some_processing_of(*cmd);
}
catch(...)
{
// Processing failed, agent can't continue work normally.
// Have to switch it to the failed state and wait for
// the deregistration.
this >>= st_failed;
}
}
...
};

This approach works but has a couple of drawbacks:

  • it's necessary to define a separate state for an agent (like st_failed shown above);
  • agent still has all its subscriptions. It means that messages will be delivered to the agent's event queue and dispatched by the agent's dispatcher. They won't be handled because there are no subscriptions in a state like st_failed, but message dispatching will consume some resources, although the agent is a special 'failed' state.

To cope with those drawbacks so_deactivate_agent was introduced in v.5.7.3. That method drops all agent's subscriptions (including deadletter handlers and delivery filters) and switches the agent to a special hidden state in that the agent doesn't handle anything.

The example above now can be rewritten that way:

class some_agent final : public so_5::agent_t
{
state_t st_working{ this, "working" };
...
void switch_to_failed_state()
{
// Notify some supervisor about the failure.
// It will deregister the whole cooperation with failed agent.
so_5::send<msg_failure>( supervisor_mbox(), ... );
// Deactivate the agent.
}
...
void so_define_agent() override
{
this >>= st_working;
...
}
void evt_some_event(mhood_t<some_msg> cmd)
{
try
{
do_some_processing_of(*cmd);
}
catch(...)
{
// Processing failed, agent can't continue work normally.
// Have to switch it to the failed state and wait for
// the deregistration.
switch_to_failed_state();
}
}
...
};
Note
The method uses so_change_state(), so it has all requirements of so_change_state(). Because the agent state will be changed, so_deactivate_state() has to be called on the working thread assigned to the agent by the dispatcher, and so_deactivate_state() can't be invoked from a thread_safe event handler.
Attention
The method is not noexcept, it can throw an exception. So additional care has to be taken when it's called in catch-block and/or in noexcept contexts.
Since
v.5.7.3

◆ so_default_state()

const state_t & so_5::agent_t::so_default_state ( ) const
protected

◆ so_define_agent()

void so_5::agent_t::so_define_agent ( )
protectedvirtual

Hook on define agent for SObjectizer.

This method is called by SObjectizer during the cooperation registration process before agent will be bound to its working thread.

Should be used by the agent to make necessary message subscriptions.

Usage sample;

class a_sample_t : public so_5::agent_t
{
// ...
virtual void
void evt_handler_1( mhood_t< message1 > msg );
// ...
void evt_handler_N( mhood_t< messageN > & msg );
};
void
a_sample_t::so_define_agent()
{
// Make subscriptions...
so_subscribe( m_mbox1 )
.in( m_state_1 )
.event( &a_sample_t::evt_handler_1 );
// ...
so_subscribe( m_mboxN )
.in( m_state_N )
.event( &a_sample_t::evt_handler_N );
}
Examples:
so_5/chameneos_prealloc_msgs/main.cpp, so_5/chameneos_simple/main.cpp, so_5/chstate/main.cpp, so_5/chstate_msg_tracing/main.cpp, so_5/coop_notification/main.cpp, so_5/coop_user_resources/main.cpp, so_5/custom_direct_mbox/main.cpp, so_5/custom_error_logger/main.cpp, so_5/dispatcher_for_children/main.cpp, so_5/dispatcher_hello/main.cpp, so_5/dispatcher_restarts/main.cpp, so_5/hardwork_imit/main.cpp, so_5/hello_all/main.cpp, so_5/hello_delay/main.cpp, so_5/hello_evt_handler/main.cpp, so_5/hello_evt_lambda/main.cpp, so_5/hello_periodic/main.cpp, so_5/machine_control/main.cpp, so_5/many_timers/main.cpp, so_5/named_dispatchers_layer/main.cpp, so_5/news_board/main.cpp, so_5/parent_coop/main.cpp, so_5/ping_pong_minimal/main.cpp, so_5/ping_pong_with_owner/main.cpp, so_5/prio_work_stealing/main.cpp, so_5/producer_consumer_mchain/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/subscriptions/main.cpp.

◆ so_deregister_agent_coop()

void so_5::agent_t::so_deregister_agent_coop ( int  dereg_reason)

A helper method for deregistering agent's coop.

Since
v.5.4.0

◆ so_deregister_agent_coop_normally()

void so_5::agent_t::so_deregister_agent_coop_normally ( )

◆ so_destroy_deadletter_subscription()

void so_5::agent_t::so_destroy_deadletter_subscription ( const mbox_t mbox,
const std::type_index &  msg_type 
)

Destroy a subscription for a deadletter handler.

Note
This is low-level method intended to be used by libraries writters. Do not call it directly if you don't understand its purpose and what its arguments mean. Use so_drop_deadletter_handler() instead.

This method actually destroys a subscription to deadletter handler for messages/signal of type msg_type from mbox mbox.

Note
It is safe to call this method if there is no such deadletter handler. It will do nothing in such case.
Since
v.5.5.21
Parameters
mboxMessage's mbox.
msg_typeMessage type.

◆ so_destroy_event_subscription()

void so_5::agent_t::so_destroy_event_subscription ( const mbox_t mbox,
const std::type_index &  subscription_type,
const state_t target_state 
)
inline

Destroy event subscription.

Note
This method was introduced in v.5.5.21 to allow manipulation of agent's subscriptions from outside of an agent.
It is safe to try to destroy nonexistent subscription.
Since
v.5.5.21
Parameters
mboxMessage's mbox.
subscription_typeMessage's type.
target_stateTarget state of a subscription.

◆ so_direct_mbox()

const mbox_t & so_5::agent_t::so_direct_mbox ( ) const

◆ so_drop_deadletter_handler()

template<typename Message >
void so_5::agent_t::so_drop_deadletter_handler ( const so_5::mbox_t mbox)
inline

Drops the subscription for deadletter handler.

A message type must be specified explicitely via template parameter.

Usage example:

class demo : public so_5::agent_t {
void some_deadletter_handler(mhood_t<some_message> cmd) {
... // Do some stuff.
// There is no need for deadletter handler.
so_drop_deadletter_handler<some_message>(some_mbox);
}
...
};
Note
Is is safe to call this method if there is no a deadletter handler for message of type Message from message box mbox.
Template Parameters
MessageType of a message or signal for deadletter handler.
Since
v.5.5.21
Parameters
mboxA mbox from which the message is expected.

◆ so_drop_delivery_filter()

template<typename Message >
void so_5::agent_t::so_drop_delivery_filter ( const mbox_t mbox)
inlinenoexcept

Drop a delivery filter.

Since
v.5.5.5
Template Parameters
Messagetype of message filtered.
Parameters
mboxMessage box to which delivery filter was set. This must be MPMC-mbox.

◆ so_drop_subscription() [1/4]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer>::value, void >::type so_5::agent_t::so_drop_subscription ( const mbox_t mbox,
const state_t target_state,
Method_Pointer   
)
inline

Drop subscription for the state specified.

Since
v.5.2.3

This overload is indended to be used when there is an event-handler in the form of agent's method. And there is a need to unsubscribe this event handler. For example:

class demo : public so_5::agent_t {
void on_some_event(mhood_t<some_msg> cmd) {
if(cmd->some_condition)
// New subscription must be created.
so_subscribe(some_mbox).in(some_state)
.event(&demo::one_shot_message_handler);
...
}
void one_shot_message_handler(mhood_t<another_msg> cmd) {
... // Some actions.
// Subscription is no more needed.
so_drop_subscription(some_mbox, some_state,
&demo::one_shot_message_handler);
}
};
Note
Doesn't throw if there is no such subscription.
Subscription is removed even if agent was subscribed for this message type with different method pointer. The pointer to event routine is necessary only to detect MSG type.

◆ so_drop_subscription() [2/4]

template<class Message >
void so_5::agent_t::so_drop_subscription ( const mbox_t mbox,
const state_t target_state 
)
inline

Drop subscription for the state specified.

Since
v.5.5.3

Usage example:

class demo : public so_5::agent_t {
void on_turn_listening_on(mhood_t<turn_on> cmd) {
// New subscription must be created.
so_subscribe(cmd->listeting_mbox()).in(some_state)
.event([this](mhood_t<state_change_notify> cmd) {...});
...
}
void on_turn_listening_off(mhood_t<turn_off> cmd) {
// Subscription is no more needed.
so_drop_subscription<state_change_notify>(cmd->listening_mbox(), some_state);
...
}
};
Note
Doesn't throw if there is no such subscription.

◆ so_drop_subscription() [3/4]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer>::value, void >::type so_5::agent_t::so_drop_subscription ( const mbox_t mbox,
Method_Pointer   
)
inline

Drop subscription for the default agent state.

Since
v.5.2.3

This overload is indended to be used when there is an event-handler in the form of agent's method. And there is a need to unsubscribe this event handler. For example:

class demo : public so_5::agent_t {
void on_some_event(mhood_t<some_msg> cmd) {
if(cmd->some_condition)
// New subscription must be created.
so_subscribe(some_mbox)
.event(&demo::one_shot_message_handler);
...
}
void one_shot_message_handler(mhood_t<another_msg> cmd) {
... // Some actions.
// Subscription is no more needed.
&demo::one_shot_message_handler);
}
};
Note
Doesn't throw if there is no such subscription.
Subscription is removed even if agent was subscribed for this message type with different method pointer. The pointer to event routine is necessary only to detect Msg type.

◆ so_drop_subscription() [4/4]

template<class Message >
void so_5::agent_t::so_drop_subscription ( const mbox_t mbox)
inline

Drop subscription for the default agent state.

Since
v.5.5.3

Usage example:

class demo : public so_5::agent_t {
void on_turn_listening_on(mhood_t<turn_on> cmd) {
// New subscription must be created.
so_subscribe(cmd->listening_mbox())
.event([this](mhood_t<state_change_notify> cmd) {...});
...
}
void on_turn_listening_off(mhood_t<turn_off> cmd) {
// Subscription is no more needed.
so_drop_subscription<state_change_notify>(cmd->listening_mbox());
...
}
};
Note
Doesn't throw if there is no such subscription.

◆ so_drop_subscription_for_all_states() [1/2]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer>::value, void >::type so_5::agent_t::so_drop_subscription_for_all_states ( const mbox_t mbox,
Method_Pointer   
)
inline

Drop subscription for all states.

Since
v.5.2.3

Usage example:

class demo : public so_5::agent_t {
state_t st_working{this}, st_waiting{this}, st_stopping{this};
...
void on_turn_listening_on(mhood_t<turn_on> cmd) {
// Make subscriptions for message of type state_change_notify.
st_working.event(cmd->listening_mbox(),
&demo::on_state_notify_when_working);
st_waiting.event(cmd->listening_mbox(),
&demo::on_state_notify_when_waiting);
st_waiting.event(cmd->listening_mbox(),
&demo::on_state_notify_when_stopping);
...
}
void on_turn_listening_off(mhood_t<turn_off> cmd) {
// Subscriptions are no more needed.
// All three event handlers for state_change_notify
// will be unsubscribed.
so_drop_subscription_for_all_states(cmd->listening_mbox(),
&demo::on_state_notify_when_working);
}
...
void on_state_notify_when_working(mhood_t<state_change_notify> cmd) {...}
void on_state_notify_when_waiting(mhood_t<state_change_notify> cmd) {...}
void on_state_notify_when_stopping(mhood_t<state_change_notify> cmd) {...}
};
Note
Doesn't throw if there is no any subscription for that mbox and message type.
Subscription is removed even if agent was subscribed for this message type with different method pointer. The pointer to event routine is necessary only to detect Msg type.
Since v.5.5.21 this method also drops the subscription for a deadletter handler for that type of message/signal.

◆ so_drop_subscription_for_all_states() [2/2]

template<class Message >
void so_5::agent_t::so_drop_subscription_for_all_states ( const mbox_t mbox)
inline

Drop subscription for all states.

Since
v.5.5.3

Usage example:

class demo : public so_5::agent_t {
state_t st_working{this}, st_waiting{this}, st_stopping{this};
...
void on_turn_listening_on(mhood_t<turn_on> cmd) {
// Make subscriptions for message of type state_change_notify.
st_working.event(cmd->listening_mbox(),
[this](mhood_t<state_change_notify> cmd) {...});
st_waiting.event(cmd->listening_mbox(),
[this](mhood_t<state_change_notify> cmd) {...});
st_waiting.event(cmd->listening_mbox(),
[this](mhood_t<state_change_notify> cmd) {...});
...
}
void on_turn_listening_off(mhood_t<turn_off> cmd) {
// Subscriptions are no more needed.
// All three event handlers for state_change_notify
// will be unsubscribed.
so_drop_subscription_for_all_states<state_change_notify>(cmd->listening_mbox());
}
...
};
Note
Doesn't throw if there is no any subscription for that mbox and message type.
Since v.5.5.21 this method also drops the subscription for a deadletter handler for that type of message/signal.

◆ so_environment()

environment_t & so_5::agent_t::so_environment ( ) const

◆ so_evt_finish()

void so_5::agent_t::so_evt_finish ( )
virtual

Hook of agent finish in SObjectizer.

It is guaranteed that this method will be called last just before deattaching agent from it's working thread.

This method should be used to perform some cleanup actions on it's working thread.

class a_sample_t : public so_5::agent_t
{
// ...
virtual void
// ...
};
a_sample_t::so_evt_finish()
{
std::cout << "last agent activity";
if( so_current_state() == m_db_error_happened )
{
// Delete the DB connection on the same thread where
// connection was established and where some
// error happened.
m_db.release();
}
}
Examples:
so_5/disp/main.cpp, so_5/hello_world/main.cpp, so_5/parent_coop/main.cpp, and so_5/ping_pong_with_owner/main.cpp.

◆ so_evt_start()

void so_5::agent_t::so_evt_start ( )
virtual

Hook on agent start inside SObjectizer.

It is guaranteed that this method will be called first just after end of the cooperation registration process.

During cooperation registration agent is bound to some working thread. And the first method which is called for the agent on that working thread context is this method.

class a_sample_t : public so_5::agent_t
{
// ...
virtual void
// ...
};
a_sample_t::so_evt_start()
{
std::cout << "first agent action on bound dispatcher" << std::endl;
... // Some application logic actions.
}
Examples:
so_5/chameneos_prealloc_msgs/main.cpp, so_5/chameneos_simple/main.cpp, so_5/chstate/main.cpp, so_5/chstate_msg_tracing/main.cpp, so_5/coop_notification/main.cpp, so_5/coop_user_resources/main.cpp, so_5/custom_direct_mbox/main.cpp, so_5/custom_error_logger/main.cpp, so_5/deadletter_handler/main.cpp, so_5/disp/main.cpp, so_5/dispatcher_for_children/main.cpp, so_5/dispatcher_hello/main.cpp, so_5/dispatcher_restarts/main.cpp, so_5/exception_logger/main.cpp, so_5/exception_reaction/main.cpp, so_5/hardwork_imit/main.cpp, so_5/hello_all/main.cpp, so_5/hello_delay/main.cpp, so_5/hello_evt_handler/main.cpp, so_5/hello_evt_lambda/main.cpp, so_5/hello_periodic/main.cpp, so_5/hello_world/main.cpp, so_5/intercom_statechart/main.cpp, so_5/machine_control/main.cpp, so_5/make_new_direct_mbox/main.cpp, so_5/many_timers/main.cpp, so_5/named_dispatchers_layer/main.cpp, so_5/nohandler_msg_tracing/main.cpp, so_5/parent_coop/main.cpp, so_5/ping_pong/main.cpp, so_5/ping_pong_minimal/main.cpp, so_5/ping_pong_with_owner/main.cpp, so_5/prio_work_stealing/main.cpp, so_5/producer_consumer_mchain/main.cpp, so_5/queue_size_stats/main.cpp, so_5/redirect_and_transform/main.cpp, so_5/simple_message_deadline/main.cpp, so_5/state_deep_history/main.cpp, so_5/stop_guard/main.cpp, so_5/subscriptions/main.cpp, and so_5/two_handlers/main.cpp.

◆ so_exception_reaction()

exception_reaction_t so_5::agent_t::so_exception_reaction ( ) const
virtual

A reaction from SObjectizer to an exception from agent's event.

Since
v.5.2.3

If an exception is going out from agent's event it will be caught by SObjectizer. Then SObjectizer will call this method and perform some actions in dependence of return value.

Note
Since v.5.3.0 default implementation calls coop_t::exception_reaction() for agent's cooperation object.
Examples:
so_5/exception_logger/main.cpp, and so_5/exception_reaction/main.cpp.

◆ so_has_deadletter_handler()

template<typename Message >
bool so_5::agent_t::so_has_deadletter_handler ( const so_5::mbox_t mbox) const
inlinenoexcept

Checks the presence of deadletter handler for a message of a specific type from a specific mbox.

Message type must be specified explicitely via template parameter Message.

Returns
true if a deadletter for a message/signal of type Message from message mbox mbox exists.

Usage example:

class demo : public so_5::agent_t {
void on_some_request(mhood_t<request_data> cmd) {
if(!so_has_deadletter_handler<some_message>(some_mbox))
// There is no deadletter handler yet.
// It should be created now.
some_mbox,
[this](mhood_t<some_message> cmd) {...});
...
}
};
Template Parameters
MessageType of a message or signal for deadletter handler.
Since
v.5.5.21
Parameters
mboxA mbox from which the message is expected.

◆ so_has_subscription() [1/4]

template<class Message >
bool so_5::agent_t::so_has_subscription ( const mbox_t mbox,
const state_t target_state 
) const
inlinenoexcept

Check the presence of a subscription.

This method can be used to avoid an exception from so_subscribe() in the case if the subscription is already present. For 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(!so_has_subscription<message>(cmd->mbox(), so_default_state()))
{
// There is no subscription yet. New subscription can be
// created.
so_subscribe(cmd->mbox()).event(...);
}
}
Note
Please do not call this method from outside of working context of the agent.
Returns
true if subscription is present for target_state.
Template Parameters
Messagea type of message/signal subscription to which must be checked.
Since
v.5.5.19.5
Parameters
mboxA mbox from which message/signal of type Message is expected.
target_stateA target state for the subscription.

◆ so_has_subscription() [2/4]

template<class Message >
bool so_5::agent_t::so_has_subscription ( const mbox_t mbox) const
inlinenoexcept

Check the presence of a subscription in the default_state.

This method can be used to avoid an exception from so_subscribe() in the case if the subscription is already present. For 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(!so_has_subscription<message>(cmd->mbox()))
{
// There is no subscription yet. New subscription can be
// created.
so_subscribe(cmd->mbox()).event(...);
}
}
Note
Please do not call this method from outside of working context of the agent.
Returns
true if subscription is present for the default_state.
Template Parameters
Messagea type of message/signal subscription to which must be checked.
Since
v.5.5.19.5
Parameters
mboxA mbox from which message/signal of type Message is expected.

◆ so_has_subscription() [3/4]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer>::value, bool >::type so_5::agent_t::so_has_subscription ( const mbox_t mbox,
const state_t target_state,
Method_Pointer   
) const
inlinenoexcept

Check the presence of a subscription.

Type of message is deducted from event-handler signature.

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(!so_has_subscription(cmd->mbox(), my_state, &my_agent::my_event))
{
// There is no subscription yet. New subscription can be
// created.
so_subscribe(cmd->mbox()).event(...);
}
}
Note
Please do not call this method from outside of working context of the agent.
Returns
true if subscription is present for target_state.
Since
v.5.5.19.5
Parameters
mboxA mbox from which message/signal is expected.
target_stateA target state for the subscription.

◆ so_has_subscription() [4/4]

template<typename Method_Pointer >
std::enable_if< details::is_agent_method_pointer< details::method_arity::unary, Method_Pointer>::value, bool >::type so_5::agent_t::so_has_subscription ( const mbox_t mbox,
Method_Pointer   
) const
inlinenoexcept

Check the presence of a subscription.

Subscription is checked for the default agent state.

Type of message is deducted from event-handler signature.

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(!so_has_subscription(cmd->mbox(), &my_agent::my_event))
{
// There is no subscription yet. New subscription can be
// created.
so_subscribe(cmd->mbox()).event(...);
}
}
Note
Please do not call this method from outside of working context of the agent.
Returns
true if subscription is present for the default state.
Since
v.5.5.19.5
Parameters
mboxA mbox from which message/signal is expected.

◆ so_initiate_agent_definition()

void so_5::agent_t::so_initiate_agent_definition ( )
protected

A correct initiation of so_define_agent method call.

Since
v.5.4.0

Before the actual so_define_agent() method it is necessary to temporary set working thread id. And then drop this id to non-actual value after so_define_agent() return.

Because of that this method must be called during cooperation registration procedure instead of direct call of so_define_agent().

◆ so_is_active_state()

bool so_5::agent_t::so_is_active_state ( const state_t state_to_check) const
noexcept

Is a state activated?

Since
v.5.5.15
Note
Since v.5.5.15 a state can have substates. For example state A can have substates B and C. If B is the current state then so_current_state() will return a reference to B. But state A is active too because it is a superstate for B. Method so_is_active_state(A) will return true in that case:
class demo : public so_5::agent_t
{
state_t A{ this, "A" };
state_t B{ initial_substate_of{ A }, "B" };
state_t C{ substate_of{ A }, "C" };
...
void some_event()
{
this >>= C;
assert( C == so_current_state() );
assert( !( A == so_current_state() ) );
assert( so_is_active_state(A) );
...
}
};
Attention
This method is not thread safe. Be careful calling this method from outside of agent's working thread.
Returns
true if state state_to_check is the current state or if the current state is a substate of state_to_check.

◆ so_make_new_direct_mbox()

mbox_t so_5::agent_t::so_make_new_direct_mbox ( )

Create a new direct mbox for that agent.

This method creates a new MPSC mbox which is connected with that agent. Only agent for that so_make_new_direct_mbox() has been called can make subscriptions for a new mbox.

Note. The new mbox doesn't replaces the standard direct mbox for the agent. Old direct mbox is still here and can still be used for sending messages to the agent. But new mbox is not related to the old direct mbox: they are different mboxes and can be used for different subscriptions. For example:

class my_agent final : public so_5::agent_t {
...
void so_evt_start() override {
so_subscribe_self().event( [](mhood_t<hello>) {
std::cout << "hello from the direct mbox" << std::endl;
} );
const new_mbox = so_make_new_direct_mbox();
so_subscribe( new_mbox ).event( [](mhood_t<hello) {
std::cout << "hello from a new mbox" << std::endl;
}
so_5::send<hello>(*this);
so_5::send<hello>(new_mbox);
}
};

The output will be:

hello from the direct mbox
hello from a new mbox
Since
v.5.6.0
Examples:
so_5/make_new_direct_mbox/main.cpp.

◆ so_priority()

priority_t so_5::agent_t::so_priority ( ) const
inline

Get the priority of the agent.

Since
v.5.5.8

◆ so_set_delivery_filter() [1/2]

template<typename Message >
void so_5::agent_t::so_set_delivery_filter ( const mbox_t mbox,
delivery_filter_unique_ptr_t  filter 
)
inline

Set a delivery filter.

Since
v.5.5.5
Note
Since v.5.7.4 it can be used for mutable messages too (if mbox is MPSC mbox). In that case Message should be in form so_5::mutable_msg<Message>.
Template Parameters
Messagetype of message to be filtered.
Parameters
mboxMessage box from which message is expected. This must be MPMC-mbox.
filterDelivery filter instance.
Examples:
so_5/machine_control/main.cpp.

◆ so_set_delivery_filter() [2/2]

template<typename Lambda >
void so_5::agent_t::so_set_delivery_filter ( const mbox_t mbox,
Lambda &&  lambda 
)

Set a delivery filter.

Since
v.5.5.5
Template Parameters
Lambdatype of lambda-function or functional object which must be used as message filter.
Usage sample:
void my_agent::so_define_agent() {
so_set_delivery_filter( temp_sensor,
[]( const current_temperature & msg ) {
return !is_normal_temperature( msg );
} );
...
}
Parameters
mboxMessage box from which message is expected. This must be MPMC-mbox.
lambdaDelivery filter as lambda-function or functional object.

◆ so_set_delivery_filter_for_mutable_msg()

template<typename Lambda >
void so_5::agent_t::so_set_delivery_filter_for_mutable_msg ( const mbox_t mbox,
Lambda &&  lambda 
)

Set a delivery filter for a mutable message.

Since
v.5.7.4
Template Parameters
Lambdatype of lambda-function or functional object which must be used as message filter.
Note
The content of the message will be passed to delivery-filter lambda-function by a const reference.
Usage sample:
void my_agent::so_define_agent() {
[]( const current_temperature & msg ) {
return !is_normal_temperature( msg );
} );
...
}
Parameters
mboxMessage box from which message is expected. This must be MPMC-mbox.
lambdaDelivery filter as lambda-function or functional object.

◆ so_subscribe()

subscription_bind_t so_5::agent_t::so_subscribe ( const mbox_t mbox_ref)
inline

Initiate subscription.

This method starts a subscription procedure by returning an instance of subscription_bind_t. The subscription details and the completion of a subscription is controlled by this subscription_bind_t object.

Usage sample:

void a_sample_t::so_define_agent()
{
// Subscription for state `state_one`
so_subscribe( mbox_target )
.in( state_one )
.event( &a_sample_t::evt_sample_handler );
// Subscription for the default state.
so_subscribe( another_mbox )
.event( &a_sample_t::evt_another_handler );
// Subscription for several event handlers in the default state.
so_subscribe( yet_another_mbox )
.event( &a_sample_t::evt_yet_another_handler )
// Lambda-function can be used as event handler too.
.event( [this](mhood_t<some_message> cmd) {...} );
// Subscription for several event handlers.
// All of them will be subscribed for states first_state and second_state.
so_subscribe( some_mbox )
.in( first_state )
.in( second_state )
.event( &a_sample_t::evt_some_handler_1 )
.event( &a_sample_t::evt_some_handler_2 )
.event( &a_sample_t::evt_some_handler_3 );
}
Parameters
mbox_refMbox for messages to subscribe.
Examples:
so_5/adv_thread_pool_fifo/main.cpp, so_5/hello_periodic/main.cpp, so_5/machine_control/main.cpp, so_5/make_new_direct_mbox/main.cpp, so_5/news_board/main.cpp, so_5/ping_pong/main.cpp, so_5/ping_pong_minimal/main.cpp, so_5/prio_work_stealing/main.cpp, and so_5/producer_consumer_mchain/main.cpp.

◆ so_subscribe_deadletter_handler()

template<typename Event_Handler >
void so_5::agent_t::so_subscribe_deadletter_handler ( const so_5::mbox_t mbox,
Event_Handler &&  handler,
thread_safety_t  thread_safety = thread_safety_t::unsafe 
)
inline

Create a subscription for deadletter handler for a specific message from a specific mbox.

Type of a message for deadletter handler will be detected automatically from the signature of the handler.

A deadletter handler can be a pointer to method of agent or lambda-function. The handler should have one of the following format:

void deadletter_handler(message_type);
void deadletter_handler(const message_type &);
void deadletter_handler(mhood_t<message_type>);

Usage example:

class demo : public so_5::agent_t {
void on_some_message(mhood_t<some_message> cmd) {...}
...
virtual void so_define_agent() override {
// Create deadletter handler via pointer to method.
// Event handler will be not-thread-safe.
&demo::on_some_message );
// Create deadletter handler via lambda-function.
status_mbox(), // Any mbox can be used, not only agent's direct mbox.
[](mhood_t<status_request> cmd) {
so_5::send<current_status>(cmd->reply_mbox, "workind");
},
// This handler will be thread-safe one.
}
};
Exceptions
so_5::exception_tin the case when the subscription of a deadletter handler for type msg_type from mbox is already exists.
Since
v.5.5.21
Examples:
so_5/deadletter_handler/main.cpp.

◆ so_subscribe_self()

subscription_bind_t so_5::agent_t::so_subscribe_self ( )
inline

Initiate subscription to agent's direct mbox.

Since
v.5.5.1

Note that is just a short form of:

void a_sample_t::so_define_agent()
{
.in( some_state )
.in( another_state )
.event( some_event_handler )
.event( some_another_handler );
}

Instead of writting so_subscribe(so_direct_mbox()) it is possible to write just so_subscribe_self().

Usage sample:
void a_sample_t::so_define_agent()
{
// Subscription for state `state_one`
.in( state_one )
.event( &a_sample_t::evt_sample_handler );
// Subscription for the default state.
.event( &a_sample_t::evt_another_handler );
// Subscription for several event handlers in the default state.
.event( &a_sample_t::evt_yet_another_handler )
// Lambda-function can be used as event handler too.
.event( [this](mhood_t<some_message> cmd) {...} );
// Subscription for several event handlers.
// All of them will be subscribed for states first_state and second_state.
.in( first_state )
.in( second_state )
.event( &a_sample_t::evt_some_handler_1 )
.event( &a_sample_t::evt_some_handler_2 )
.event( &a_sample_t::evt_some_handler_3 );
}
Examples:
so_5/custom_direct_mbox/main.cpp, so_5/custom_error_logger/main.cpp, so_5/deadletter_handler/main.cpp, so_5/hardwork_imit/main.cpp, so_5/hello_evt_handler/main.cpp, so_5/hello_evt_lambda/main.cpp, so_5/machine_control/main.cpp, so_5/make_new_direct_mbox/main.cpp, so_5/many_timers/main.cpp, so_5/modify_resend_as_immutable/main.cpp, so_5/mutable_msg_agents/main.cpp, so_5/named_dispatchers_layer/main.cpp, so_5/news_board/main.cpp, so_5/parent_coop/main.cpp, so_5/prio_work_stealing/main.cpp, so_5/producer_consumer_mchain/main.cpp, so_5/stop_guard/main.cpp, and so_5/two_handlers/main.cpp.

◆ so_switch_to_awaiting_deregistration_state()

void so_5::agent_t::so_switch_to_awaiting_deregistration_state ( )

Switching agent to special state in case of unhandled exception.

Note
Since v.5.7.3 it's implemented via so_deactivate_agent().
Since
5.2.3

◆ so_was_defined()

bool so_5::agent_t::so_was_defined ( ) const
protected

Is method define_agent already called?

Usage sample:

class a_sample_t : public so_5::agent_t
{
// ...
public:
void
set_target_mbox( const so_5::mbox_t & mbox )
{
// mbox cannot be changed after agent registration.
if( !so_was_defined() )
{
m_target_mbox = mbox;
}
}
private:
so_5::mbox_t m_target_mbox;
};

◆ tuning_options()

static agent_tuning_options_t so_5::agent_t::tuning_options ( )
inlinestatic

Create tuning options object with default values.

Since
v.5.5.3

Friends And Related Function Documentation

◆ intrusive_ptr_t

template<typename T >
friend class intrusive_ptr_t
friend

◆ so_5::enveloped_msg::impl::agent_demand_handler_invoker_t

◆ so_5::impl::internal_agent_iface_t

◆ so_5::impl::mpsc_mbox_t

friend class so_5::impl::mpsc_mbox_t
friend

◆ so_5::impl::state_switch_guard_t

friend class so_5::impl::state_switch_guard_t
friend

◆ state_t

friend class state_t
friend

◆ subscription_bind_t

friend class subscription_bind_t
friend

Member Data Documentation

◆ deep_history

constexpr const state_t::history_t so_5::agent_t::deep_history
static
Initial value:

Short alias for so_5::state_t::history_t::deep.

Since
v.5.5.15

◆ m_agent_coop

coop_t* so_5::agent_t::m_agent_coop
private

Agent is belong to this cooperation.

◆ m_current_state_ptr

const state_t* so_5::agent_t::m_current_state_ptr
private

Current agent state.

◆ m_current_status

agent_status_t so_5::agent_t::m_current_status
private

Current agent status.

Since
v.5.5.18

◆ m_delivery_filters

std::unique_ptr< impl::delivery_filter_storage_t > so_5::agent_t::m_delivery_filters
private

Delivery filters for that agents.

Since
v.5.5.5
Note
Storage is created only when necessary.

◆ m_direct_mbox

const mbox_t so_5::agent_t::m_direct_mbox
private

A direct mbox for the agent.

Since
v.5.4.0

◆ m_env

environment_t& so_5::agent_t::m_env
private

SObjectizer Environment for which the agent is belong.

◆ m_event_queue

event_queue_t* so_5::agent_t::m_event_queue
private

A pointer to event_queue.

Since
v.5.5.8

After binding to the dispatcher is it pointed to the actual event queue.

After shutdown it is set to nullptr.

Attention
Access to m_event_queue value must be done only under acquired m_event_queue_lock.

◆ m_event_queue_lock

default_rw_spinlock_t so_5::agent_t::m_event_queue_lock
private

Event queue operation protector.

Since
v.5.5.8

Initially m_event_queue is NULL. It is changed to actual value in so_bind_to_dispatcher() method. And reset to nullptr again in shutdown_agent().

nullptr in m_event_queue means that methods push_event() will throw away any new demand.

It is necessary to provide guarantee that m_event_queue will be reset to nullptr in shutdown_agent() only if there is no working push_event() methods. To do that default_rw_spinlock_t is used. Method push_event() acquire it in read-mode and shutdown_agent() acquires it in write-mode. It means that shutdown_agent() cannot get access to m_event_queue until there is working push_event().

◆ m_handler_finder

handler_finder_t so_5::agent_t::m_handler_finder
private

Function for searching event handler.

Since
v.5.5.9
Note
The value is set only once in the constructor and doesn't changed anymore.

◆ m_message_limits

std::unique_ptr< message_limit::impl::info_storage_t > so_5::agent_t::m_message_limits
private

Run-time information for message limits.

Since
v.5.5.4

Created only of message limits are described in agent's tuning options.

Attention
This attribute must be initialized before the m_direct_mbox attribute. It is because the value of m_message_limits is used in m_direct_mbox creation. Because of that m_message_limits is declared before m_direct_mbox.

◆ m_priority

const priority_t so_5::agent_t::m_priority
private

Priority of the agent.

Since
v.5.5.8

◆ m_state_listener_controller

impl::state_listener_controller_t so_5::agent_t::m_state_listener_controller
private

State listeners controller.

◆ m_subscriptions

impl::subscription_storage_unique_ptr_t so_5::agent_t::m_subscriptions
private

All agent's subscriptions.

Since
v.5.4.0

◆ m_working_thread_id

so_5::current_thread_id_t so_5::agent_t::m_working_thread_id
private

Working thread id.

Since
v.5.4.0

Some actions like managing subscriptions and changing states are enabled only on working thread id.

◆ shallow_history

constexpr const state_t::history_t so_5::agent_t::shallow_history
static
Initial value:

Short alias for so_5::state_t::history_t::shallow.

Since
v.5.5.15

◆ st_default

const state_t so_5::agent_t::st_default { self_ptr(), "<DEFAULT>" }
private

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