#include <iostream>
#include <iterator>
#include <numeric>
#include <cstdlib>
enum color_t
{
BLUE = 0,
RED = 1,
YELLOW = 2,
FADED = 3
};
{
color_t m_color;
msg_meeting_result( color_t color )
: m_color( color )
{}
};
msg_meeting_result_smart_ref_t;
{
color_t m_color;
msg_meeting_result_smart_ref_t m_result_message;
msg_meeting_request(
color_t color,
msg_meeting_result_smart_ref_t result_message )
: m_who( who )
, m_color( color )
, m_result_message( result_message )
{}
};
msg_meeting_request_smart_ref_t;
{
int m_creatures_met;
msg_shutdown_ack( int creatures_met )
: m_creatures_met( creatures_met )
{}
};
{
public :
a_meeting_place_t(
context_t ctx,
int creatures,
int meetings )
, m_creatures_alive( creatures )
, m_remaining_meetings( meetings )
, m_total_meetings( 0 )
{}
{
this >>= st_empty;
st_empty
.event( &a_meeting_place_t::evt_first_creature )
.event( &a_meeting_place_t::evt_shutdown_ack );
st_one_creature_inside
.event( &a_meeting_place_t::evt_second_creature );
}
void evt_first_creature( mhood_t< msg_meeting_request > evt )
{
if( m_remaining_meetings )
{
this >>= st_one_creature_inside;
m_first_creature_info = evt.make_reference();
}
else
evt->m_who->deliver_signal< msg_shutdown_request >();
}
void evt_second_creature(
const msg_meeting_request & evt )
{
evt.m_result_message->m_color =
m_first_creature_info->m_color;
m_first_creature_info->m_result_message->m_color = evt.m_color;
evt.m_who->deliver_message( evt.m_result_message );
m_first_creature_info->m_who->deliver_message(
m_first_creature_info->m_result_message );
m_first_creature_info.reset();
--m_remaining_meetings;
this >>= st_empty;
}
void evt_shutdown_ack(
const msg_shutdown_ack & evt )
{
m_total_meetings += evt.m_creatures_met;
if( 0 >= --m_creatures_alive )
{
std::cout << "Total: " << m_total_meetings << std::endl;
}
}
private :
const state_t st_empty{
this,
"empty" };
const state_t st_one_creature_inside{
this,
"one_creature_inside" };
int m_creatures_alive;
int m_remaining_meetings;
int m_total_meetings;
msg_meeting_request_smart_ref_t m_first_creature_info;
};
{
public :
a_creature_t(
context_t ctx,
color_t color )
, m_meeting_place_mbox(
std::move(meeting_place_mbox) )
, m_meeting_counter( 0 )
, m_response_message( new msg_meeting_result( color ) )
, m_request_message( new msg_meeting_request(
so_direct_mbox(),
color,
m_response_message ) )
{}
{
.
event( &a_creature_t::evt_meeting_result )
.
event< msg_shutdown_request >(
&a_creature_t::evt_shutdown_request );
}
{
m_meeting_place_mbox->deliver_message( m_request_message );
}
void evt_meeting_result(
const msg_meeting_result & evt )
{
m_request_message->m_color = complement( evt.m_color );
m_meeting_counter++;
m_meeting_place_mbox->deliver_message( m_request_message );
}
void evt_shutdown_request()
{
m_request_message->m_color = FADED;
std::cout << "Creatures met: " << m_meeting_counter << std::endl;
so_5::send< msg_shutdown_ack >(
m_meeting_place_mbox, m_meeting_counter );
}
private :
int m_meeting_counter;
msg_meeting_result_smart_ref_t m_response_message;
msg_meeting_request_smart_ref_t m_request_message;
color_t complement( color_t other ) const
{
switch( m_request_message->m_color )
{
case BLUE:
return other == RED ? YELLOW : RED;
case RED:
return other == BLUE ? YELLOW : BLUE;
case YELLOW:
return other == BLUE ? RED : BLUE;
case FADED:
break;
}
return m_request_message->m_color;
}
};
const int CREATURE_COUNT = 4;
{
{
color_t creature_colors[ CREATURE_COUNT ] =
{ BLUE, RED, YELLOW, BLUE };
auto a_meeting_place = coop.
make_agent< a_meeting_place_t >(
CREATURE_COUNT,
meetings );
for( int i = 0; i != CREATURE_COUNT; ++i )
{
a_meeting_place->so_direct_mbox(),
creature_colors[ i ] );
}
} );
}
int main( int argc, char ** argv )
{
try
{
const int meetings = 2 == argc ? std::atoi( argv[1] ) : 10;
init( env, meetings );
} );
}
catch( const std::exception & ex )
{
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}
return 0;
}