#include <iostream>
#include <string>
using namespace std::chrono;
{
using clock = steady_clock;
public :
struct ask_status {};
struct status_idle {};
struct status_in_progress {};
struct status_finished { unsigned long long m_ms; };
struct start_ping_pong { unsigned int m_pings; };
struct ping_pong_stopped {};
a_supervisor(
context_t ctx,
, m_req_mbox{ move(req_mbox) }
, m_chain{ move(chain) }
{}
virtual void
so_define_agent() override
{
this >>= st_idle;
st_idle
.event( m_req_mbox, [this]( ask_status ) {
so_5::send< status_idle >( m_chain );
} )
.
event( m_req_mbox, &a_supervisor::evt_start_ping_pong );
st_started
.event( m_req_mbox, [this]( ask_status ) {
so_5::send< status_in_progress >( m_chain );
} )
.
event( [
this]( ping_pong_stopped ) {
m_last_duration_ms = static_cast< unsigned long long >(
duration_cast< milliseconds >(
clock::now() - m_started_at ).count() );
this >>= st_finished;
so_5::send< status_finished >( m_chain, m_last_duration_ms );
} );
st_finished
.event( m_req_mbox, [this]( ask_status ) {
so_5::send< status_finished >( m_chain, m_last_duration_ms );
} )
.
event( m_req_mbox, &a_supervisor::evt_start_ping_pong );
}
private :
clock::time_point m_started_at;
unsigned long long m_last_duration_ms;
void evt_start_ping_pong( start_ping_pong evt )
{
this >>= st_started;
m_started_at = clock::now();
so_environment() )->binder(),
{
struct ping{ unsigned int m_v; };
struct pong{ unsigned int m_v; };
auto parent_mbox = so_direct_mbox();
pinger.on_start( [ponger, evt] {
so_5::send< ping >( ponger, evt.m_pings );
} )
[ponger, parent_mbox, &coop]( pong reply ) {
if( reply.m_v )
so_5::send< ping >( ponger, reply.m_v - 1 );
else
{
so_5::send< ping_pong_stopped >( parent_mbox );
}
} );
ponger.event( ponger, [pinger]( ping req ) {
so_5::send< pong >( pinger, req.m_v );
} );
} );
}
};
void demo()
{
coop.
make_agent< a_supervisor >( req_mbox, chain );
} );
while( true )
{
cout << "Enter command (status,start,exit): " << flush;
string choice;
cin >> choice;
if( "status" == choice )
{
so_5::send< a_supervisor::ask_status >( req_mbox );
from( chain ).empty_timeout( milliseconds(200) ),
[]( a_supervisor::status_idle ) {
cout << "status: IDLE" << endl;
},
[]( a_supervisor::status_in_progress ) {
cout << "status: IN PROGRESS" << endl;
},
[]( a_supervisor::status_finished v ) {
cout << "status: finished in " << v.m_ms << "ms" << endl;
} );
if( !r.handled() )
cout << "--- no response from supervisor ---" << endl;
}
else if( "start" == choice )
{
cout << "Enter pings count: " << flush;
unsigned int pings = 0;
cin >> pings;
so_5::send< a_supervisor::start_ping_pong >( req_mbox, pings );
}
else if( "exit" == choice || "quit" == choice )
break;
}
}
int main()
{
try
{
demo();
}
catch( const exception & x )
{
cerr << "Exception: " << x.what() << endl;
return 2;
}
return 0;
}