use mpstthree::binary::struct_trait::{end::End, session::Session}; use mpstthree::binary_atmp::struct_trait::{recv::RecvTimed, send::SendTimed}; use mpstthree::generate; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use rand::{thread_rng, Rng}; use std::collections::HashMap; use std::error::Error; use std::time::Instant; generate!( "atmp_interleaved", MeshedChannelsBarber, Barber, ShopBarber, 2, MeshedChannelsClient, Client, ShopClient, 2, fork_mpst ); // Number of seats static SEATS: usize = 3; static LOOPS: usize = 100; // Struct for labels struct Full; struct Seat; struct Available; struct Ready; struct Customer; struct Description; struct Haircut; struct Pay; // Barber type Recurs0fromShopBarberToBarber = RecvTimed; enum Branching0fromShopBarberToBarber { Done(MeshedChannelsBarber), Available( MeshedChannelsBarber< SendTimed, RoleShopBarber>, NameBarber, >, ), } type Recurs1fromShopBarberToBarber = RecvTimed; enum Branching1fromShopBarberToBarber { Available( MeshedChannelsBarber< RecvTimed, RoleShopBarber>, NameBarber, >, ), } type Recurs2fromShopBarberToBarber = RecvTimed; enum Branching2fromShopBarberToBarber { Available( MeshedChannelsBarber< RecvTimed, RoleShopBarber>, NameBarber, >, ), } type Recurs3fromShopBarberToBarber = RecvTimed; enum Branching3fromShopBarberToBarber { Available( MeshedChannelsBarber< SendTimed, RoleShopBarber>, NameBarber, >, ), } type Recurs4fromShopBarberToBarber = RecvTimed; enum Branching4fromShopBarberToBarber { Available( MeshedChannelsBarber< RecvTimed, RoleShopBarber>, NameBarber, >, ), } type Recurs5fromShopBarberToBarber = RecvTimed; // ShopBarber type Choose0fromShopBarberToBarber = ::Dual; type Choose1fromShopBarberToBarber = ::Dual; type Choose2fromShopBarberToBarber = ::Dual; type Choose3fromShopBarberToBarber = ::Dual; type Choose4fromShopBarberToBarber = ::Dual; type Choose5fromShopBarberToBarber = ::Dual; // Client type Recurs0fromShopClientToClient = RecvTimed; enum Branching0fromShopClientToClient { Done(MeshedChannelsClient), Full( MeshedChannelsClient< RecvTimed< Full, 'a', 0, true, 10, true, ' ', RecvTimed, >, RoleShopClient>, NameClient, >, ), Available( MeshedChannelsClient< RecvTimed, RoleShopClient>, NameClient, >, ), } type Recurs1fromShopClientToClient = RecvTimed; enum Branching1fromShopClientToClient { Available( MeshedChannelsClient< RecvTimed, RoleShopClient>, NameClient, >, ), } type Recurs2fromShopClientToClient = RecvTimed; enum Branching2fromShopClientToClient { Available( MeshedChannelsClient< SendTimed, RoleShopClient>, NameClient, >, ), } type Recurs3fromShopClientToClient = RecvTimed; enum Branching3fromShopClientToClient { Available( MeshedChannelsClient< RecvTimed, RoleShopClient>, NameClient, >, ), } type Recurs4fromShopClientToClient = RecvTimed; enum Branching4fromShopClientToClient { Available( MeshedChannelsClient< SendTimed, RoleShopClient>, NameClient, >, ), } type Recurs5fromShopClientToClient = RecvTimed; // ShopClient type Choose0fromShopClientToClient = ::Dual; type Choose1fromShopClientToClient = ::Dual; type Choose2fromShopClientToClient = ::Dual; type Choose3fromShopClientToClient = ::Dual; type Choose4fromShopClientToClient = ::Dual; type Choose5fromShopClientToClient = ::Dual; // Creating the MP sessions // Barber type EndpointBarber0 = MeshedChannelsBarber, NameBarber>; type EndpointBarber1 = MeshedChannelsBarber, NameBarber>; type EndpointBarber2 = MeshedChannelsBarber, NameBarber>; type EndpointBarber3 = MeshedChannelsBarber, NameBarber>; type EndpointBarber4 = MeshedChannelsBarber, NameBarber>; // ShopBarber type EndpointShopBarber0 = MeshedChannelsBarber; type EndpointShopBarberDone = MeshedChannelsBarber; // Recurs type EndpointShopBarberRecurs1 = MeshedChannelsBarber; type EndpointShopBarberRecurs2 = MeshedChannelsBarber; type EndpointShopBarberRecurs3 = MeshedChannelsBarber; type EndpointShopBarberRecurs4 = MeshedChannelsBarber; // Full branches type EndpointShopBarberAvailabe = MeshedChannelsBarber< RecvTimed, RoleBarber, NameShopBarber, >; type EndpointShopBarberCustomer = MeshedChannelsBarber< SendTimed, RoleBarber, NameShopBarber, >; type EndpointShopBarberDescription = MeshedChannelsBarber< SendTimed, RoleBarber, NameShopBarber, >; type EndpointShopBarberHaircut = MeshedChannelsBarber< RecvTimed, RoleBarber, NameShopBarber, >; type EndpointShopBarberPay = MeshedChannelsBarber< SendTimed, RoleBarber, NameShopBarber, >; // Client type EndpointClient0 = MeshedChannelsClient< RecvTimed, RoleShopClient, NameClient, >; type EndpointClient1 = MeshedChannelsClient< RecvTimed, RoleShopClient, NameClient, >; type EndpointClient2 = MeshedChannelsClient< RecvTimed, RoleShopClient, NameClient, >; type EndpointClient3 = MeshedChannelsClient< RecvTimed, RoleShopClient, NameClient, >; type EndpointClient4 = MeshedChannelsClient< RecvTimed, RoleShopClient, NameClient, >; // ShopClient type EndpointShopClient0 = MeshedChannelsClient; type EndpointShopClientDone = MeshedChannelsClient; type EndpointShopClientFull = MeshedChannelsClient< SendTimed, RoleClient, NameShopClient, >; // Recurs type EndpointShopClientRecurs1 = MeshedChannelsClient; type EndpointShopClientRecurs2 = MeshedChannelsClient; type EndpointShopClientRecurs3 = MeshedChannelsClient; type EndpointShopClientRecurs4 = MeshedChannelsClient; // Full branches type EndpointShopClientSeat = MeshedChannelsClient< SendTimed, RoleClient, NameShopClient, >; type EndpointShopClientReady = MeshedChannelsClient< SendTimed, RoleClient, NameShopClient, >; type EndpointShopClientDescription = MeshedChannelsClient< RecvTimed, RoleClient, NameShopClient, >; type EndpointShopClientHaircut = MeshedChannelsClient< SendTimed, RoleClient, NameShopClient, >; type EndpointShopClientPay = MeshedChannelsClient< RecvTimed, RoleClient, NameShopClient, >; ///////////////////////// // Barber fn recurs_0_barber( s: EndpointBarber0, all_clocks: &mut HashMap, ) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); recurs_1_barber(s, all_clocks) } fn recurs_1_barber( s: EndpointBarber0, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching0fromShopBarberToBarber::Done(s) => { s.close() }, Branching0fromShopBarberToBarber::Available(s) => { let s = s.send(Available { }, all_clocks)?; recurs_2_barber(s, all_clocks) }, } ) } fn recurs_2_barber( s: EndpointBarber1, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching1fromShopBarberToBarber::Available(s) => { let (_customer, s) = s.recv(all_clocks)?; recurs_3_barber(s, all_clocks) }, } ) } fn recurs_3_barber( s: EndpointBarber2, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching2fromShopBarberToBarber::Available(s) => { let (_description, s) = s.recv(all_clocks)?; recurs_4_barber(s, all_clocks) }, } ) } fn recurs_4_barber( s: EndpointBarber3, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching3fromShopBarberToBarber::Available(s) => { let s = s.send(Haircut { }, all_clocks)?; recurs_5_barber(s, all_clocks) }, } ) } fn recurs_5_barber( s: EndpointBarber4, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching4fromShopBarberToBarber::Available(s) => { let (_pay, s) = s.recv(all_clocks)?; recurs_1_barber(s, all_clocks) }, } ) } // Shop fn endpoint_shop( s_shop_barber: EndpointShopBarber0, all_clocks_one: &mut HashMap, s_shop_client: EndpointShopClient0, all_clocks_two: &mut HashMap, ) -> Result<(), Box> { all_clocks_one.insert('a', Instant::now()); all_clocks_two.insert('a', Instant::now()); recurs_0_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, LOOPS, 0, ) } fn recurs_0_shop( s_shop_barber: EndpointShopBarber0, all_clocks_one: &mut HashMap, s_shop_client: EndpointShopClient0, all_clocks_two: &mut HashMap, loops: usize, number_clients: usize, ) -> Result<(), Box> { match loops { // If end of the day 0 => { let s_shop_barber: EndpointShopBarberDone = choose_mpst_shopbarber_to_all!( s_shop_barber, all_clocks_one, Branching0fromShopBarberToBarber::Done, ); let _ = s_shop_barber.close(); let s_shop_client: EndpointShopClientDone = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching0fromShopClientToClient::Done, ); s_shop_client.close() } _ => { // A client will come with a proba of 10% if thread_rng().gen_range(1..=10) == 1 && number_clients < SEATS { let s_shop_barber: EndpointShopBarberAvailabe = choose_mpst_shopbarber_to_all!( s_shop_barber, all_clocks_one, Branching0fromShopBarberToBarber::Available, ); let s_shop_client: EndpointShopClientSeat = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching0fromShopClientToClient::Available, ); let s_shop_client = s_shop_client.send(Seat {}, all_clocks_two)?; let (_available, s_shop_barber) = s_shop_barber.recv(all_clocks_one)?; recurs_1_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, loops - 1, number_clients + 1, ) } else { let s_shop_client: EndpointShopClientFull = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching0fromShopClientToClient::Full, ); let s_shop_client = s_shop_client.send(Full {}, all_clocks_two)?; recurs_0_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, loops - 1, number_clients, ) } } } } fn recurs_1_shop( s_shop_barber: EndpointShopBarberRecurs1, all_clocks_one: &mut HashMap, s_shop_client: EndpointShopClientRecurs1, all_clocks_two: &mut HashMap, loops: usize, number_clients: usize, ) -> Result<(), Box> { let s_shop_barber: EndpointShopBarberCustomer = choose_mpst_shopbarber_to_all!( s_shop_barber, all_clocks_one, Branching1fromShopBarberToBarber::Available ); let s_shop_client: EndpointShopClientReady = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching1fromShopClientToClient::Available ); let s_shop_client = s_shop_client.send(Ready {}, all_clocks_two)?; let s_shop_barber = s_shop_barber.send(Customer {}, all_clocks_one)?; recurs_2_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, loops, number_clients, ) } fn recurs_2_shop( s_shop_barber: EndpointShopBarberRecurs2, all_clocks_one: &mut HashMap, s_shop_client: EndpointShopClientRecurs2, all_clocks_two: &mut HashMap, loops: usize, number_clients: usize, ) -> Result<(), Box> { let s_shop_barber: EndpointShopBarberDescription = choose_mpst_shopbarber_to_all!( s_shop_barber, all_clocks_one, Branching2fromShopBarberToBarber::Available ); let s_shop_client: EndpointShopClientDescription = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching2fromShopClientToClient::Available ); // Decription let (description, s_shop_client) = s_shop_client.recv(all_clocks_two)?; let s_shop_barber = s_shop_barber.send(description, all_clocks_one)?; recurs_3_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, loops, number_clients, ) } fn recurs_3_shop( s_shop_barber: EndpointShopBarberRecurs3, all_clocks_one: &mut HashMap, s_shop_client: EndpointShopClientRecurs3, all_clocks_two: &mut HashMap, loops: usize, number_clients: usize, ) -> Result<(), Box> { let s_shop_barber: EndpointShopBarberHaircut = choose_mpst_shopbarber_to_all!( s_shop_barber, all_clocks_one, Branching3fromShopBarberToBarber::Available ); let s_shop_client: EndpointShopClientHaircut = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching3fromShopClientToClient::Available ); // Haircut let (haircut, s_shop_barber) = s_shop_barber.recv(all_clocks_one)?; let s_shop_client = s_shop_client.send(haircut, all_clocks_two)?; recurs_4_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, loops, number_clients, ) } fn recurs_4_shop( s_shop_barber: EndpointShopBarberRecurs4, all_clocks_one: &mut HashMap, s_shop_client: EndpointShopClientRecurs4, all_clocks_two: &mut HashMap, loops: usize, number_clients: usize, ) -> Result<(), Box> { let s_shop_barber: EndpointShopBarberPay = choose_mpst_shopbarber_to_all!( s_shop_barber, all_clocks_one, Branching4fromShopBarberToBarber::Available ); let s_shop_client: EndpointShopClientPay = choose_mpst_shopclient_to_all!( s_shop_client, all_clocks_two, Branching4fromShopClientToClient::Available ); // Pay let (pay, s_shop_client) = s_shop_client.recv(all_clocks_two)?; let s_shop_barber = s_shop_barber.send(pay, all_clocks_one)?; recurs_0_shop( s_shop_barber, all_clocks_one, s_shop_client, all_clocks_two, loops, number_clients - 1, ) } // Client fn recurs_0_client( s: EndpointClient0, all_clocks: &mut HashMap, ) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); recurs_1_client(s, all_clocks) } fn recurs_1_client( s: EndpointClient0, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching0fromShopClientToClient::Done(s) => { s.close() }, Branching0fromShopClientToClient::Full(s) => { let (_full, s) = s.recv(all_clocks)?; recurs_1_client(s, all_clocks) }, Branching0fromShopClientToClient::Available(s) => { let (_seat, s) = s.recv(all_clocks)?; recurs_2_client(s, all_clocks) }, } ) } fn recurs_2_client( s: EndpointClient1, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching1fromShopClientToClient::Available(s) => { let (_ready, s) = s.recv(all_clocks)?; recurs_3_client(s, all_clocks) }, } ) } fn recurs_3_client( s: EndpointClient2, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching2fromShopClientToClient::Available(s) => { let s = s.send(Description { }, all_clocks)?; recurs_4_client(s, all_clocks) }, } ) } fn recurs_4_client( s: EndpointClient3, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching3fromShopClientToClient::Available(s) => { let (_haircut, s) = s.recv(all_clocks)?; recurs_5_client(s, all_clocks) }, } ) } fn recurs_5_client( s: EndpointClient4, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!( s, all_clocks, { Branching4fromShopClientToClient::Available(s) => { let s = s.send(Pay { }, all_clocks)?; recurs_1_client(s, all_clocks) }, } ) } ///////////////////////// fn main() { let (thread_barber, thread_client, thread_shop) = fork_mpst(recurs_0_barber, recurs_0_client, endpoint_shop); thread_barber.join().unwrap(); thread_client.join().unwrap(); thread_shop.join().unwrap(); }