#include <iostream>
#include <iterator>
#include <numeric>
#include <cstdlib>
enum color_t
{
BLUE = 0,
RED = 1,
YELLOW = 2,
FADED = 3
};
struct msg_meeting_request
{
color_t m_color;
};
struct msg_meeting_result
{
color_t m_color;
};
struct msg_shutdown_ack
{
int m_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 );
}
private :
void evt_first_creature(
const msg_meeting_request & evt )
{
if( m_remaining_meetings )
{
this >>= st_one_creature_inside;
m_first_creature_mbox = evt.m_who;
m_first_creature_color = evt.m_color;
}
else
so_5::send< msg_shutdown_request >( evt.m_who );
}
void evt_second_creature(
const msg_meeting_request & evt )
{
so_5::send< msg_meeting_result >(
evt.m_who, m_first_creature_color );
so_5::send< msg_meeting_result >(
m_first_creature_mbox, evt.m_color );
--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;
}
}
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;
color_t m_first_creature_color = { FADED };
};
{
public :
a_creature_t(
context_t ctx,
color_t color )
, m_meeting_place_mbox( std::move(meeting_place_mbox) )
, m_meeting_counter( 0 )
, m_color( color )
{}
{
.
event( &a_creature_t::evt_meeting_result )
.
event( &a_creature_t::evt_shutdown_request );
}
{
so_5::send< msg_meeting_request >(
m_meeting_place_mbox,
}
private :
void evt_meeting_result(
const msg_meeting_result & evt )
{
m_color = complement( evt.m_color );
m_meeting_counter++;
so_5::send< msg_meeting_request >(
m_meeting_place_mbox,
}
void evt_shutdown_request( mhood_t< msg_shutdown_request > )
{
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 );
}
int m_meeting_counter;
color_t m_color;
color_t complement( color_t other ) const noexcept
{
switch( 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_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;
}