Menu

so-5.3.0 Ad-hoc agents

Yauheni Akhotnikau

Introduction

A new type of agents is introduced in v.5.3.0 -- ad-hoc agents. They are agents which could be constructed and registered without necessity of defining dedicated C++ class.

To construct ad-hoc agent is necessary to call define_method for cooperation object. This method returns a special proxy object which is used to definition of behaviour of new agent. For example this method chain creates agents which handles a message and a signal.

auto coop = env.create_coop( "sample" );
// Definition of ad-hoc agent.
coop->define_agent()
   // First event for that agent.
   .event(
      // A mbox as message source.
      some_mbox,
      // Event handling code. Type of message is deduced automatically.
      []( const msg_convert & msg ) -> int {
         return std::atoi( msg.m_value );
      } )
   // Second event for that agent.
   .event(
      // A mbox as message source.
      some_mbox,
      // Type of signal. Must be specified explicitly.
      so_5::signal< msg_get_status >,
      // Event handling code.
      []() -> std::string {
         return "ready";
      } );

Details

Binding ad-hoc agent to the specified dispatcher

Ad-hoc agent uses default cooperation dispatcher binder:

auto coop = env.create_coop( "active", so_5::disp::active_obj::create_disp_binder( "1" ) );
// First active agent.
coop->define_agent().event( ... );
// Second active agent.
coop->define_agent().event( ... );

But another dispatcher binder could be specified as an argument for define_agent() method:

auto coop = env.create_coop( "active", so_5::disp::active_obj::create_disp_binder( "1" ) );
// This agent will be active because it uses cooperation binder object.
coop->define_agent().event( ... );
// This agent will be passive.
coop->define_agent( so_5::rt::create_default_disp_binder() ).event( ... );

Specifying starting and finish ad-hoc agent actions

Ordinary agents have so_evt_start() and so_evt_finish() methods which are called at the start and at the end of agent work. Similar behavior could be specified to ad-hoc agents by on_start() and on_finish() methods chains:

auto coop = env.create_coop( "demo" );
coop->define_agent()
   // A start action for the agent.
   .on_start( []() {
        std::cout << "Agent started" << std::endl;
      } )
   // A finish action for the agent.
   .on_finish( []() {
        std::cout << "Agent finished" << std::endl;
      } )
   ...

Specifying exception reaction for ad-hoc agent

Ordinary agents could reimplement so_exception_reaction() method to specify reaction to non-handled exceptions. Ad-hoc agents do not have that method. If ad-hoc agent should specify some reaction to non-handled exception this could be done by exception_reaction() method chain:

coop->define_agent()
   // Exception from that agent could be safely ignored.
   .exception_reaction( so_5::rt::ignore_exception )
   .event( target_mbox,
      [target_mbox]( const msg_payment_request & msg ) {
         if( "RUR" == msg.currency_code() )
            {
               std::unique_ptr< msg_payment_request > new_request( new msg_payment_request( msg ) );
               new_request->set_currency_code( "RUB" );
               target_mbox->deliver_message( std::move( new_request ) );
            }
         else
            target_mbox->deliver_message( new msg_payment_request( msg ) );
      } );

Major differences from ordinal agents

Ad-hoc agents have the following major differences from ordinary agents.

No access to SObjectizer Environment

Ad-hoc agents have no access to so_environment. An ordinary agent could do:

void a_some_agent_t::evt_shutdown_signal()
   {
      // SObjectizer RunTime should be shut down.
      so_environment().stop();
   }

Ad-hoc agent should store reverence to so_enviroment as a capture variable:

auto coop = so_environment().create_coop( "child" );
so_5::rt::so_environment_t & env = so_environment();
coop->define_agent()
   .event( some_mbox, so_5::signal< msg_shutdown_signal >,
      // Note that env is captured by reference!
      [&env]() { env.stop(); } );

No states

Ad-hoc agents cannot have states. Ordinary agents could define states by creating so_5::rt::state_t objects and then switching from one state to another. Ad-hoc agents have only one state which is hidden from the developer.

No access to cooperation

Ad-hoc agents have no access to the cooperation they belong. The ordinary agent could do:

void a_some_agent_t::evt_some_event()
   {
      if( /* Work is impossible */ )
         so_environment().deregister_coop( so_coop_name() );
   }

But ad-hoc agent cannot.

Inability to receive event_data_t as argument

Lambda functions which are used as event handlers for ad-hoc agents should have one of the following prototypes:

// For ordinal message handling.
Result (const Message & )
// For signal handling.
Result ()

It is impossible to pass event_data_t object as argument to ad-hoc agent's event. So it is impossible to resend the same message object from ad-hoc agent's event (because there is not access to event_data_t::make_reference() method).


Related

Wiki: so-5.3 By Example Minimal Ping-Pong
Wiki: so-5.4 By Example Minimal Ping-Pong
Wiki: so-5.5 By Example Minimal Ping-Pong