Skip to content

Commit

Permalink
Remove all generic context code
Browse files Browse the repository at this point in the history
  • Loading branch information
sgdxbc committed Aug 18, 2024
1 parent 9f2f20e commit a87cc79
Show file tree
Hide file tree
Showing 3 changed files with 32 additions and 111 deletions.
38 changes: 30 additions & 8 deletions src/bin/workload/clients.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bytes::Bytes;
use neatworks::{
codec::Encode,
event::{
task::{self, run_with_schedule, ContextCarrier, ScheduleState},
task::{self, run_with_schedule, ScheduleState},
Erase, SendEvent, Untyped,
},
net::{
Expand Down Expand Up @@ -105,20 +105,38 @@ pub async fn pbft(
let (schedule_sender, mut schedule_receiver) = unbounded_channel();
let (sender, mut receiver) = unbounded_channel();

let net_task = udp::run(
&socket,
pbft::messages::codec::to_client_decode(Erase::new(sender.clone())),
);

let mut context = pbft::client::context::Context::<ContextCarrier, _, _, _> {
type S = pbft::client::State<SocketAddr>;
type Net =
Encode<pbft::messages::codec::ToReplica<SocketAddr>, IndexNet<SocketAddr, Arc<UdpSocket>>>;
type Upcall = UnboundedSender<InvokeOk<Bytes>>;
type Schedule = task::erase::ScheduleState<S, Context>;
struct Context {
net: Net,
upcall: Upcall,
schedule: Schedule,
}
impl pbft::client::Context<SocketAddr> for Context {
type Net = Net;
type Upcall = Upcall;
type Schedule = Schedule;
fn net(&mut self) -> &mut Self::Net {
&mut self.net
}
fn upcall(&mut self) -> &mut Self::Upcall {
&mut self.upcall
}
fn schedule(&mut self) -> &mut Self::Schedule {
&mut self.schedule
}
}
let mut context = Context {
net: pbft::messages::codec::to_replica_encode(IndexNet::new(
replica_addrs,
None,
socket.clone(),
)),
upcall: upcall_sender,
schedule: Erase::new(ScheduleState::new(schedule_sender)),
_m: Default::default(),
};
let client_task = run_with_schedule(
Untyped::new(pbft::client::State::new(random(), addr, config)),
Expand All @@ -127,6 +145,10 @@ pub async fn pbft(
&mut schedule_receiver,
|context| &mut *context.schedule,
);
let net_task = udp::run(
&socket,
pbft::messages::codec::to_client_decode(Erase::new(sender.clone())),
);

run_until(
invoke_task.run(Erase::new(sender), upcall_receiver),
Expand Down
53 changes: 1 addition & 52 deletions src/event/task.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use std::{collections::HashMap, marker::PhantomData};
use std::collections::HashMap;

use derive_where::derive_where;
use tokio::{
Expand All @@ -18,57 +18,6 @@ pub mod erase {
pub type ScheduleState<S, C> = Erase<S, C, super::ScheduleState<UntypedEvent<S, C>>>;
}

// a "stub", or marker type that indicates the task based context is being used
// in a context type that refers to itself (on type level, not memory reference)
//
// the private PhantomData<()> prevents it from being constructed anywhere
// outside. and it indeed should not be ever constructed; it only shows up in
// type annotations, as a "placeholder" to take place for the actual generics
// that would refer the context's own type and cannot be written out directly
// anywhere outside the context definition
//
// the marker type seems to have no implementation. ideally it should have
// several implementation "blanket over" a generic state e.g. for schedule
//
// struct ContextOf<S>(PhantomData<S>) // the desired form of `Context`
//
// trait On<Context> {
// type Out;
// }
//
// impl<State, Context> On<Context> for ContextOf<State>
// where
// /* whatever bounds the state and context */
// {
// type Out = erase::ScheduleState<State, Context>
// }
//
// this would not work (at least for now) because of the limitations by how
// compiler deals with `where` clauses involving types refer to each other (the
// details do not fit here but in short it will probably result in
// "error[E0275]: overflow evaluating the requirement"). the current workaround
// comes with three parts
// * move bounds in `where` clauses to associated types
// * `impl` on specialization instead of blanket to avoid explicitly writing out
// the `where` clauses, but relying on the requirements trivially hold for the
// specialized states and contexts
// * because the `On<_>::Out` has context-specified bounds (for the first
// point), and one context type can have at most one `On<Self>` bound (or the
// `impl`s of those bounds will need to `where` on each other again), invent
// dedicated `On<_>` trait for every context that produces all types that
// refer back to the context type, instead of one universal trait for
// schedule, one for worker upcall, etc
//
// as the result, the `impl`s of `ContextOf<_>` all lives in the use sites and
// are for some specialization. but in sprite those `impl`s are together
// recovering the necessary part of the blanket above
//
// since the `impl`s are becoming specialized, it is unnecessary for this marker
// to be generic over state (or anything). the (becoming unnecessary)
// PhantomData<_> is saved to continue preventing `Context` value being
// constructed, which is still desired despiting the workaround
pub struct ContextCarrier(PhantomData<()>);

impl<M: Into<N>, N> SendEvent<M> for UnboundedSender<N> {
fn send(&mut self, event: M) -> anyhow::Result<()> {
UnboundedSender::send(self, event.into())
Expand Down
52 changes: 1 addition & 51 deletions src/pbft/client.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@ use bytes::Bytes;

use crate::{
codec::Payload,
event::{OnErasedEvent, ScheduleEvent, SendEvent, ActiveTimer},
event::{ActiveTimer, OnErasedEvent, ScheduleEvent, SendEvent},
net::{combinators::All, events::Recv, Addr, SendMessage},
workload::events::{Invoke, InvokeOk},
};
Expand Down Expand Up @@ -129,53 +129,3 @@ impl<A: Addr> State<A> {
context.net().send(dest, request)
}
}

pub mod context {
use std::marker::PhantomData;

use super::*;

pub struct Context<O: On<Self>, N, U, A> {
pub net: N,
pub upcall: U,
pub schedule: O::Schedule,
pub _m: PhantomData<A>,
}

pub trait On<C> {
type Schedule: ScheduleEvent<events::Resend>;
}

impl<O: On<Self>, N, U, A> super::Context<A> for Context<O, N, U, A>
where
N: SendMessage<u8, Request<A>> + SendMessage<All, Request<A>>,
U: SendEvent<InvokeOk<Bytes>>,
{
type Net = N;
type Upcall = U;
type Schedule = O::Schedule;
fn net(&mut self) -> &mut Self::Net {
&mut self.net
}
fn upcall(&mut self) -> &mut Self::Upcall {
&mut self.upcall
}
fn schedule(&mut self) -> &mut Self::Schedule {
&mut self.schedule
}
}

mod task {
use crate::event::task::{erase::ScheduleState, ContextCarrier as Task};

use super::*;

impl<N, U, A: Addr> On<Context<Self, N, U, A>> for Task
where
N: SendMessage<u8, Request<A>> + SendMessage<All, Request<A>> + 'static,
U: SendEvent<InvokeOk<Bytes>> + 'static,
{
type Schedule = ScheduleState<State<A>, Context<Self, N, U, A>>;
}
}
}

0 comments on commit a87cc79

Please sign in to comment.