use mpstthree::binary::struct_trait::end::End; // The basic End types use mpstthree::binary_atmp::struct_trait::{recv::RecvTimed, send::SendTimed}; // The basic timed types use mpstthree::generate_atmp; /* The macro for generating the roles and * the MeshedChannels */ use mpstthree::role::broadcast::RoleBroadcast; /* Optional: used only for protocols with * choice/offer */ use mpstthree::role::end::RoleEnd; // The final type for the stacks and the names of the roles use std::collections::HashMap; // Used for storing clocks use std::error::Error; // Used for functions returning _affine_ types use std::time::Instant; // Used for clocks // use std::thread::sleep; // Used for pausing a thread // use std::time::Duration; // Used for declaring the duration for sleep generate_atmp!(MeshedChannels, A, B); // generates meshed channels for 3 roles // Payload types struct Request; struct Response; struct Stop; // Binary types for A type StartA0 = RecvTimed< Request, 'a', 0, true, 1, true, ' ', SendTimed, >; // RecvTimed a Request then SendTimed a choice type OrderingA0 = RoleB; // Stack for recv then sending a choice type LoopA0 = SendTimed; // SendTimed a choice type OrderingLoopA0 = RoleBroadcast; // Stack for sending a choice type MoreA1 = SendTimed< Response, 'a', 0, true, 1, true, ' ', SendTimed, >; // RecvTimed Response then send a choice type OrderingMoreA1 = RoleB; // Stack for the previous binary type type DoneA1 = SendTimed; // RecvTimed Stop type OrderingDoneA1 = RoleB; // Stack for the previous binary type // Binary types for B type StartB0 = SendTimed< Request, 'a', 0, true, 1, true, ' ', RecvTimed, >; // SendTimed a Request then RecvTimed a choice type OrderingB0 = RoleA>; // Stack for send then receiving a choice from A type LoopB0 = RecvTimed; // RecvTimed a choice type OrderingLoopB0 = RoleA; // Stack for recv a choice type MoreB1 = RecvTimed< Response, 'a', 0, true, 1, true, ' ', RecvTimed, >; // RecvTimed Request then SendTimed Response then receive a choice type OrderingMoreB1 = RoleA>; // Stack for the previous binary type type DoneB1 = RecvTimed; // SendTimed Stop type OrderingDoneB1 = RoleA; // Stack for the previous binary type enum Branching0fromAtoB { // Sum type containing the different paths of the choice More(MeshedChannels), Done(MeshedChannels), } // Creating the endpoints // A type EndpointAMore = MeshedChannels; type EndpointADone = MeshedChannels; type EndpointALoop = MeshedChannels; type EndpointA = MeshedChannels; // B type EndpointBLoop = MeshedChannels; type EndpointB = MeshedChannels; fn endpoint_a(s: EndpointA, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let (_, s) = s.recv(all_clocks)?; recurs_a(s, 5, all_clocks) } fn recurs_a( s: EndpointALoop, loops: i32, all_clocks: &mut HashMap, ) -> Result<(), Box> { if loops > 0 { let s: EndpointAMore = choose_mpst_a_to_all!(s, all_clocks, Branching0fromAtoB::More); let s = s.send(Response {}, all_clocks)?; recurs_a(s, loops - 1, all_clocks) } else { let s: EndpointADone = choose_mpst_a_to_all!(s, all_clocks, Branching0fromAtoB::Done); let s = s.send(Stop {}, all_clocks)?; s.close() } } fn endpoint_b(s: EndpointB, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); // sleep(Duration::from_secs(2)); let s = s.send(Request {}, all_clocks)?; recurs_b(s, all_clocks) } fn recurs_b( s: EndpointBLoop, all_clocks: &mut HashMap, ) -> Result<(), Box> { offer_mpst!(s, all_clocks, { Branching0fromAtoB::More(s) => { let (_, s) = s.recv(all_clocks)?; recurs_b(s, all_clocks) }, Branching0fromAtoB::Done(s) => { let (_, s) = s.recv(all_clocks)?; s.close() }, }) } fn main() { let (thread_a, thread_b) = fork_mpst(endpoint_a, endpoint_b); println!("Thread a: {:?}", thread_a.join()); println!("Thread b: {:?}", thread_b.join()); }