use crate::Context;
use crate::merge::MergePolicy;
use crate::relay::{
BackpressurePolicy, BoundDim, IngressOutcome, Overflow, RelayCell, RelayConfigError,
};
use crate::slot::SlotHandle;
pub struct Outbox<T, M> {
relay: RelayCell<T, M>,
}
impl<T, M> Outbox<T, M>
where
T: Clone + PartialEq + 'static,
M: MergePolicy<T>,
{
pub fn new(ctx: &Context, high_water: u64) -> Result<Self, RelayConfigError> {
Self::with_overflow(ctx, BoundDim::Count, high_water, Overflow::Conflate)
}
pub fn with_overflow(
ctx: &Context,
dimension: BoundDim,
high_water: u64,
overflow: Overflow,
) -> Result<Self, RelayConfigError> {
let policy = BackpressurePolicy::new(ctx, dimension, high_water, high_water / 2, overflow);
Ok(Self {
relay: RelayCell::new(ctx, policy)?,
})
}
pub fn send(&self, ctx: &Context, op: T) -> IngressOutcome {
self.relay.ingress(ctx, op)
}
pub fn drain(&self, ctx: &Context) -> Option<T> {
self.relay.drain(ctx)
}
pub fn is_full(&self) -> SlotHandle<bool> {
self.relay.is_full()
}
pub fn relay(&self) -> &RelayCell<T, M> {
&self.relay
}
}
pub struct Inbox<T, M> {
relay: RelayCell<T, M>,
credits: u64,
max_credits: u64,
}
impl<T, M> Inbox<T, M>
where
T: Clone + PartialEq + 'static,
M: MergePolicy<T>,
{
pub fn new(ctx: &Context, high_water: u64, max_credits: u64) -> Result<Self, RelayConfigError> {
Self::with_overflow(ctx, high_water, Overflow::Conflate, max_credits)
}
pub fn with_overflow(
ctx: &Context,
high_water: u64,
overflow: Overflow,
max_credits: u64,
) -> Result<Self, RelayConfigError> {
let policy =
BackpressurePolicy::new(ctx, BoundDim::Count, high_water, high_water / 2, overflow);
Ok(Self {
relay: RelayCell::new(ctx, policy)?,
credits: max_credits,
max_credits,
})
}
pub fn ready(&self) -> bool {
self.credits > 0
}
pub fn credits(&self) -> u64 {
self.credits
}
pub fn receive(&mut self, ctx: &Context, op: T) -> IngressOutcome {
self.credits = self.credits.saturating_sub(1);
self.relay.ingress(ctx, op)
}
pub fn consume(&mut self, ctx: &Context, replenish: u64) -> Option<T> {
let out = self.relay.drain(ctx);
self.credits = (self.credits + replenish).min(self.max_credits);
out
}
}