#![allow( clippy::type_complexity, clippy::too_many_arguments, clippy::large_enum_variant )] use mpstthree::binary::struct_trait::end::End; use mpstthree::binary_atmp::struct_trait::{recv::RecvTimed, send::SendTimed}; use mpstthree::generate_atmp; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use rand::{random, thread_rng, Rng}; use std::collections::HashMap; use std::error::Error; use std::time::Instant; // See the folder scribble_protocols for the related Scribble protocol // Create the new MeshedChannels for three participants and the close and fork functions generate_atmp!(MeshedChannels, A, C, S); // Types // A type Choose0fromCtoA = SendTimed; type Choose0fromCtoS = SendTimed; // A enum Branching0fromCtoA { Accept( MeshedChannels< RecvTimed, End, RoleC, NameA, >, ), Quit( MeshedChannels< RecvTimed, End, RoleC, NameA, >, ), } // S enum Branching0fromCtoS { Accept( MeshedChannels< End, RecvTimed< i32, 'a', 0, true, 10, true, ' ', SendTimed, >, TwoRoleC, NameS, >, ), Quit( MeshedChannels< End, RecvTimed, RoleC, NameS, >, ), } type TwoRoleC = RoleC>; // Creating the MP sessions // A type EndpointA = MeshedChannels< SendTimed< i32, 'a', 0, true, 10, true, ' ', RecvTimed, >, SendTimed>, RoleS>, NameA, >; // C type EndpointC = MeshedChannels< RecvTimed, RecvTimed, RoleS>, NameC, >; type EndpointCAccept = MeshedChannels< SendTimed, SendTimed>, RoleA>>, NameC, >; type EndpointCQuit = MeshedChannels< SendTimed, SendTimed, RoleS>, NameC, >; // S type EndpointS = MeshedChannels< RecvTimed>, SendTimed< i32, 'a', 0, true, 10, true, ' ', RecvTimed, >, RoleA>>>, NameS, >; // Functions fn endpoint_a(s: EndpointA, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let s = s.send(random(), all_clocks)?; let (_empty2, s) = s.recv(all_clocks)?; let s = s.send(random(), all_clocks)?; offer_mpst!(s, all_clocks, { Branching0fromCtoA::Accept(s) => { let (_ok, s) = s.recv(all_clocks)?; s.close() }, Branching0fromCtoA::Quit(s) => { let (_ok, s) = s.recv(all_clocks)?; s.close() }, }) } fn endpoint_c(s: EndpointC, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let (_empty3, s) = s.recv(all_clocks)?; let (_empty4, s) = s.recv(all_clocks)?; let choice: i32 = thread_rng().gen_range(1..=3); if choice != 1 { let s: EndpointCAccept = choose_mpst_c_to_all!( s, all_clocks, Branching0fromCtoA::Accept, Branching0fromCtoS::Accept, ); let s = s.send(random(), all_clocks)?; let s = s.send(random(), all_clocks)?; let (_empty5, s) = s.recv(all_clocks)?; s.close() } else { let s: EndpointCQuit = choose_mpst_c_to_all!( s, all_clocks, Branching0fromCtoA::Quit, Branching0fromCtoS::Quit, ); let s = s.send(random(), all_clocks)?; let s = s.send(random(), all_clocks)?; s.close() } } fn endpoint_s(s: EndpointS, all_clocks: &mut HashMap) -> Result<(), Box> { all_clocks.insert('a', Instant::now()); let (_empty1, s) = s.recv(all_clocks)?; let s = s.send(random(), all_clocks)?; let s = s.send(random(), all_clocks)?; offer_mpst!(s, all_clocks, { Branching0fromCtoS::Accept(s) => { let (_ok, s) = s.recv(all_clocks)?; let s = s.send(random(), all_clocks)?; s.close() }, Branching0fromCtoS::Quit(s) => { let (_ok, s) = s.recv(all_clocks)?; s.close() }, }) } ///////////////////////////////////////// fn main() { let (thread_a, thread_c, thread_s) = fork_mpst(endpoint_a, endpoint_c, endpoint_s); thread_a.join().unwrap(); thread_c.join().unwrap(); thread_s.join().unwrap(); }