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 );
			} );
	}
Beispiel #2
0
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();
        }
    } );
}
Beispiel #3
0
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 ) );
				} );
	}
Beispiel #6
0
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())) );
	}
Beispiel #8
0
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 );
}