#![allow( clippy::large_enum_variant, clippy::type_complexity, clippy::too_many_arguments )] use criterion::{black_box, criterion_group, criterion_main, Criterion}; use mpstthree::binary::struct_trait::{end::End, recv::Recv, send::Send, session::Session}; use mpstthree::role::broadcast::RoleBroadcast; use mpstthree::role::end::RoleEnd; use mpstthree::{ bundle_struct_fork_close_multi, choose_mpst_multi_to_all, create_multiple_normal_name, create_multiple_normal_role_short, create_recv_mpst_session_bundle, create_send_mpst_session_bundle, offer_mpst, }; use rand::{random, thread_rng, Rng}; use std::error::Error; use std::marker; // See the folder scribble_protocols for the related Scribble protocol // Create the new MeshedChannels for three participants and the close and fork functions bundle_struct_fork_close_multi!(close_mpst_multi, fork_mpst, MeshedChannels, 3); // Create new roles // normal create_multiple_normal_role_short!(A, C, S); // Create new names create_multiple_normal_name!(NameA, NameC, NameS); // Create new send functions // A create_send_mpst_session_bundle!( send_mpst_a_to_c, RoleC, 1 | send_mpst_a_to_s, RoleS, 2 | => NameA, MeshedChannels, 3 ); // C create_send_mpst_session_bundle!( send_mpst_c_to_a, RoleA, 1 | send_mpst_c_to_s, RoleS, 2 | => NameC, MeshedChannels, 3 ); // S create_send_mpst_session_bundle!( send_mpst_s_to_c, RoleC, 2 | => NameS, MeshedChannels, 3 ); // Create new recv functions and related types // A create_recv_mpst_session_bundle!( recv_mpst_a_from_c, RoleC, 1 | => NameA, MeshedChannels, 3 ); // C create_recv_mpst_session_bundle!( recv_mpst_c_from_a, RoleA, 1 | recv_mpst_c_from_s, RoleS, 2 | => NameC, MeshedChannels, 3 ); // S create_recv_mpst_session_bundle!( recv_mpst_s_from_a, RoleA, 1 | recv_mpst_s_from_c, RoleC, 2 | => NameS, MeshedChannels, 3 ); // Types // C0 type Choose0fromCtoA = Send, End>; type Choose0fromCtoS = Send, End>; // C1 type Choose1fromCtoA = as Session>::Dual; type Choose1fromCtoS = as Session>::Dual; // A enum Branching0fromCtoA { Select(MeshedChannels, End, RoleC, NameA>), Loop( MeshedChannels< Recv>>, Send, RoleC>>>, NameA, >, ), } type Choice0fromCtoA = Recv, End>; enum Branching1fromCtoA { Yes(MeshedChannels, Send, RoleC>, NameA>), No(MeshedChannels, Send, RoleC>, NameA>), } type Choice1fromCtoA = Recv, End>; // S enum Branching0fromCtoS { Select(MeshedChannels, RoleC, NameS>), Loop(MeshedChannels, Choice0fromCtoS, RoleA>, NameS>), } type Choice0fromCtoS = Recv, End>; enum Branching1fromCtoS { Yes(MeshedChannels, Recv>, RoleA>>, NameS>), No(MeshedChannels, End, RoleA, NameS>), } type Choice1fromCtoS = Recv, End>; // Creating the MP sessions // A type ChoiceA = MeshedChannels, End, RoleC, NameA>; type EndpointA = MeshedChannels, End, RoleC, NameA>; // C type ChoiceC = MeshedChannels, Choose1fromCtoS, RoleBroadcast, NameC>; type EndpointC = MeshedChannels, Choose0fromCtoS, RoleBroadcast, NameC>; // S type ChoiceS = MeshedChannels, RoleC, NameS>; type EndpointS = MeshedChannels, RoleC, NameS>; // Functions // A fn endpoint_a(s: EndpointA) -> Result<(), Box> { offer_mpst!(s, recv_mpst_a_from_c, { Branching0fromCtoA::Select(s) => { choice_a(s) }, Branching0fromCtoA::Loop(s) => { let (query, s) = recv_mpst_a_from_c(s)?; let s = send_mpst_a_to_c(query, s); let s = send_mpst_a_to_s(random(), s); endpoint_a(s) }, }) } fn choice_a(s: ChoiceA) -> Result<(), Box> { offer_mpst!(s, recv_mpst_a_from_c, { Branching1fromCtoA::Yes(s) => { let (yes, s) = recv_mpst_a_from_c(s)?; let s = send_mpst_a_to_s(yes, s); close_mpst_multi(s) }, Branching1fromCtoA::No(s) => { let (no, s) = recv_mpst_a_from_c(s)?; let s = send_mpst_a_to_s(no, s); close_mpst_multi(s) }, }) } fn endpoint_init(s: EndpointC) -> Result<(), Box> { endpoint_c(s, LOOPS) } fn endpoint_c(s: EndpointC, loops: i32) -> Result<(), Box> { match loops { 0 => { let s = choose_mpst_multi_to_all!( s, Branching0fromCtoA::::Select, Branching0fromCtoS::::Select, => NameC, MeshedChannels, 2 ); choice_c(s) } _ => { let s = choose_mpst_multi_to_all!( s, Branching0fromCtoA::::Loop, Branching0fromCtoS::::Loop, => NameC, MeshedChannels, 2 ); let s = send_mpst_c_to_a(random(), s); let (_quote, s) = recv_mpst_c_from_a(s)?; endpoint_c(s, loops - 1) } } } fn choice_c(s: ChoiceC) -> Result<(), Box> { let choice: i32 = thread_rng().gen_range(1..3); if choice != 1 { let s = choose_mpst_multi_to_all!( s, Branching1fromCtoA::::Yes, Branching1fromCtoS::::Yes, => NameC, MeshedChannels, 2 ); let s = send_mpst_c_to_a(random(), s); let s = send_mpst_c_to_s(random(), s); let (_ack, s) = recv_mpst_c_from_s(s)?; close_mpst_multi(s) } else { let s = choose_mpst_multi_to_all!( s, Branching1fromCtoA::::No, Branching1fromCtoS::::No, => NameC, MeshedChannels, 2 ); let s = send_mpst_c_to_a(0, s); close_mpst_multi(s) } } fn endpoint_s(s: EndpointS) -> Result<(), Box> { offer_mpst!(s, recv_mpst_s_from_c, { Branching0fromCtoS::Select(s) => { choice_s(s) }, Branching0fromCtoS::Loop(s) => { let (_dummy, s) = recv_mpst_s_from_a(s)?; endpoint_s(s) }, }) } fn choice_s(s: ChoiceS) -> Result<(), Box> { offer_mpst!(s, recv_mpst_s_from_c, { Branching1fromCtoS::Yes(s) => { let (_yes, s) = recv_mpst_s_from_a(s)?; let (payment, s) = recv_mpst_s_from_c(s)?; let s = send_mpst_s_to_c(payment, s); close_mpst_multi(s) }, Branching1fromCtoS::No(s) => { let (_no, s) = recv_mpst_s_from_a(s)?; close_mpst_multi(s) }, }) } fn aux() { let (thread_a, thread_c, thread_s) = fork_mpst( black_box(endpoint_a), black_box(endpoint_init), black_box(endpoint_s), ); thread_a.join().unwrap(); thread_c.join().unwrap(); thread_s.join().unwrap(); } ///////////////////////// static LOOPS: i32 = 100; pub fn travel(c: &mut Criterion) { c.bench_function("Travel agency basic", |b| b.iter(aux)); } ///////////////////////// criterion_group! { name = bench; config = Criterion::default().significance_level(0.05).without_plots().sample_size(100000); targets = travel, } criterion_main! { bench }