#include <iostream>
#include <iterator>
#include <numeric>
#include <cstdlib>
#include <vector>
#include <mutex>
#include <tuple>
#include <random>
unsigned int random_value( unsigned int left, unsigned int right )
{
std::random_device rd;
std::mt19937 gen{ rd() };
return std::uniform_int_distribution< unsigned int >{left, right}(gen);
}
struct msg_take
{
};
struct msg_taken
{
};
{
public :
{
this >>= st_free;
st_free.event( [this]( const msg_take & evt )
{
this >>= st_taken;
} );
st_taken.event( []( const msg_take & evt )
{
so_5::send< msg_busy >( evt.m_who );
} )
.just_switch_to< msg_put >( st_free );
}
private :
const state_t st_free{
this,
"free" };
const state_t st_taken{
this,
"taken" };
};
{
public :
philosopher_t(
context_t ctx,
std::string name,
, m_name(
std::move( name ) )
, m_left_fork(
std::move( left_fork ) )
, m_right_fork(
std::move( right_fork ) )
{}
{
st_thinking.event< msg_stop_thinking >( [=]{
show_msg( "become hungry, try to take forks" );
this >>= st_hungry;
} );
st_hungry.event( [=]( const msg_taken & evt ) {
show_msg( fork_name( evt.m_who ) + " fork taken" );
m_first_taken = evt.m_who;
this >>= st_one_taken;
} )
.just_switch_to< msg_busy >( st_denied );
st_one_taken.event( [=]( const msg_taken & evt ) {
show_msg( fork_name( evt.m_who ) + " fork taken" );
show_msg( "take both forks, start eating" );
this >>= st_eating;
so_5::send_delayed< msg_stop_eating >(
*this, random_pause() );
} )
.event< msg_busy >( [=]{
show_msg( "put " + fork_name( m_first_taken ) +
" down because " + opposite_fork_name( m_first_taken ) +
" denied" );
so_5::send< msg_put >( m_first_taken );
think();
} );
st_denied.event( [=]( const msg_taken & evt ) {
show_msg( "put " + fork_name( evt.m_who ) +
" down because " + opposite_fork_name( evt.m_who ) +
" denied" );
so_5::send< msg_put >( evt.m_who );
think();
} )
.event< msg_busy >( [=]{
show_msg( "both forks busy" );
think();
} );
st_eating.event< msg_stop_eating >( [=]{
show_msg( "stop eating, put forks, return to thinking" );
so_5::send< msg_put >( m_right_fork );
so_5::send< msg_put >( m_left_fork );
think();
} );
}
{
think();
}
private :
const state_t st_one_taken{
this };
const std::string m_name;
{
return (m_left_fork == fork ? "left" : "right");
}
std::string opposite_fork_name(
const so_5::mbox_t & fork )
const {
return (m_left_fork == fork ? "right" : "left");
}
void show_msg( const std::string & msg ) const
{
std::cout << "[" << m_name << "] " << msg << std::endl;
}
void think()
{
show_msg( "start thinking" );
this >>= st_thinking;
so_5::send_delayed< msg_stop_thinking >( *this, random_pause() );
}
static std::chrono::milliseconds
random_pause()
{
return std::chrono::milliseconds( 250 + random_value( 0, 250 ) );
}
};
{
const std::size_t count = 5;
std::vector< so_5::agent_t * > forks( count, nullptr );
for( std::size_t i = 0; i != count; ++i )
for( std::size_t i = 0; i != count; ++i )
std::to_string( i ),
forks[ i ]->so_direct_mbox(),
forks[ (i + 1) % count ]->so_direct_mbox() );
});
std::this_thread::sleep_for( std::chrono::seconds(20) );
}
int main()
{
try
{
}
catch( const std::exception & ex )
{
std::cerr << "Error: " << ex.what() << std::endl;
return 1;
}
return 0;
}