void define_starter_agent( so_5::coop_t & coop, so_5::disp::prio_one_thread::strictly_ordered::private_dispatcher_t & disp ) { coop.define_agent( coop.make_agent_context() + so_5::prio::p0, disp.binder() ) .on_start( [&coop, &disp] { auto common_mbox = coop.environment().create_mbox(); coop.environment().introduce_coop( [&]( so_5::coop_t & child ) { using namespace so_5::prio; std::string & sequence = define_main_agent( child, disp, common_mbox ); define_receiver_agent( child, disp, p1, common_mbox, sequence ); define_receiver_agent( child, disp, p2, common_mbox, sequence ); define_receiver_agent( child, disp, p3, common_mbox, sequence ); define_receiver_agent( child, disp, p4, common_mbox, sequence ); define_receiver_agent( child, disp, p5, common_mbox, sequence ); define_receiver_agent( child, disp, p6, common_mbox, sequence ); define_receiver_agent( child, disp, p7, common_mbox, sequence ); } ); so_5::send< msg_hello >( common_mbox ); } ); }
void define_supervison_agent( so_5::coop_t & coop, const so_5::mbox_t & common_mbox ) { struct supervisor_data { const std::string m_expected_value; std::string m_accumulator; const std::size_t m_expected_receivers; std::size_t m_started_receivers = 0; const std::size_t m_expected_replies; std::size_t m_replies = 0; supervisor_data( std::string expected_value, std::size_t expected_receivers, std::size_t expected_replies ) : m_expected_value( std::move( expected_value ) ) , m_expected_receivers( expected_receivers ) , m_expected_replies( expected_replies ) {} }; auto data = std::make_shared< supervisor_data >( "777775555333" "777775555333" "777775555333" "777775555333" "5555333" "333" "33", 3, 3 * 20u ); coop.define_agent() .event< msg_receiver_started >( common_mbox, [common_mbox, data] { data->m_started_receivers += 1; if( data->m_started_receivers == data->m_expected_receivers ) so_5::send< msg_send_messages >( common_mbox ); } ) .event( common_mbox, [&coop, data]( const msg_reply & reply ) { data->m_replies += 1; data->m_accumulator += std::to_string( so_5::to_size_t( reply.m_priority ) ); if( data->m_replies >= data->m_expected_replies ) { if( data->m_expected_value != data->m_accumulator ) throw std::runtime_error( "values mismatch: " "expected: " + data->m_expected_value + ", actual: " + data->m_accumulator ); else coop.environment().stop(); } } ); }
void define_message_sender( so_5::coop_t & coop, so_5::disp::prio_one_thread::quoted_round_robin::private_dispatcher_t & disp, const so_5::mbox_t & common_mbox ) { coop.define_agent( coop.make_agent_context() + so_5::prio::p0, disp.binder() ) .event< msg_send_messages >( common_mbox, [common_mbox] { for( int i = 0; i != 20; ++i ) so_5::send< msg_request >( common_mbox ); } ); }
so_5::mbox_t make_logger( so_5::coop_t & coop ) { // Logger will work on its own working thread. auto logger = coop.define_agent( so_5::disp::one_thread::create_private_disp( coop.environment() )->binder() ); logger.event( logger, []( const log_msg & msg ) { std::cout << msg << std::endl; } ); return logger.direct_mbox(); }
void define_receiver_agent( so_5::coop_t & coop, so_5::disp::prio_one_thread::strictly_ordered::private_dispatcher_t & disp, so_5::priority_t priority, const so_5::mbox_t & common_mbox, std::string & sequence ) { coop.define_agent( coop.make_agent_context() + priority, disp.binder() ) .event< msg_hello >( common_mbox, [priority, &sequence] { sequence += std::to_string( static_cast< std::size_t >( priority ) ); } ); }
void define_receiver_agent( so_5::coop_t & coop, so_5::disp::prio_one_thread::quoted_round_robin::private_dispatcher_t & disp, so_5::priority_t priority, const so_5::mbox_t & common_mbox ) { coop.define_agent( coop.make_agent_context() + priority, disp.binder() ) .on_start( [common_mbox] { so_5::send< msg_receiver_started >( common_mbox ); } ) .event< msg_request >( common_mbox, [priority, common_mbox] { so_5::send< msg_reply >( common_mbox, priority ); } ); }
void fill_coop( so_5::coop_t & coop ) { using namespace so_5::disp::prio_one_thread::strictly_ordered; define_starter_agent( coop, *(create_private_disp(coop.environment())) ); }
void fill_coop( so_5::coop_t & coop ) { using namespace so_5::disp::prio_one_thread::quoted_round_robin; using namespace so_5::prio; auto common_mbox = coop.environment().create_mbox(); auto rr_disp = create_private_disp( coop.environment(), quotes_t{2} .set( p7, 5 ) .set( p5, 4 ) .set( p3, 3 ) ); define_supervison_agent( coop, common_mbox ); define_message_sender( coop, *rr_disp, common_mbox ); define_receiver_agent( coop, *rr_disp, p7, common_mbox ); define_receiver_agent( coop, *rr_disp, p5, common_mbox ); define_receiver_agent( coop, *rr_disp, p3, common_mbox ); }
void fill_demo_coop( so_5::coop_t & coop ) { const unsigned int producers = 40; // Shutdowner will work on the default dispatcher. coop.make_agent_with_binder< shutdowner >( so_5::create_default_disp_binder(), producers ); // Logger will work on its own context. const auto logger_mbox = make_logger( coop ); // Consumer agent must be created first. // It will work on its own working thread. auto consumer_mbox = coop.make_agent_with_binder< consumer >( so_5::disp::one_thread::create_private_disp( coop.environment() )->binder(), logger_mbox )->consumer_mbox(); // All producers will work on thread pool dispatcher. namespace tp_disp = so_5::disp::thread_pool; auto disp = tp_disp::create_private_disp( coop.environment() ); // All agents on this dispatcher will have independent event queues. const auto bind_params = tp_disp::bind_params_t{} .fifo( tp_disp::fifo_t::individual ) .max_demands_at_once( 1 ); // All producers can be created now. for( unsigned int i = 0; i != producers; ++i ) coop.make_agent_with_binder< producer >( disp->binder( bind_params ), "producer-" + std::to_string( i + 1 ), logger_mbox, consumer_mbox, 10u ); }