use std::rc::Rc;
use dvcompute::simulation::event::*;
use dvcompute::simulation::process::*;
use crate::simulation::block::*;
use crate::simulation::queue::*;
use crate::simulation::facility::*;
use crate::simulation::transact::*;
#[inline]
pub fn advance_block<M, T>(comp: M) -> impl Block<Input = T, Output = T>
where M: Process<Item = ()> + 'static,
T: 'static
{
cons_block(move |x| {
comp.map(move |()| x)
})
}
#[inline]
pub fn queue_block<T>(queue: Rc<Queue>, increment: isize) -> impl Block<Input = Rc<Transact<T>>, Output = Rc<Transact<T>>>
where T: 'static
{
cons_block(move |x: Rc<Transact<T>>| {
Queue::enqueue(queue, x.clone(), increment)
.map(move |()| x)
.into_process()
})
}
#[inline]
pub fn depart_block<T>(queue: Rc<Queue>, decrement: isize) -> impl Block<Input = Rc<Transact<T>>, Output = Rc<Transact<T>>>
where T: 'static
{
cons_block(move |x: Rc<Transact<T>>| {
Queue::dequeue(queue, x.clone(), decrement)
.map(move |()| x)
.into_process()
})
}
#[inline]
pub fn seize_block<T>(facility: Rc<Facility<T>>) -> impl Block<Input = Rc<Transact<T>>, Output = Rc<Transact<T>>>
where T: 'static
{
cons_block(move |x: Rc<Transact<T>>| {
seize_facility(facility, x.clone())
.map(move |()| x)
.into_process()
})
}
#[inline]
pub fn release_block<T>(facility: Rc<Facility<T>>) -> impl Block<Input = Rc<Transact<T>>, Output = Rc<Transact<T>>>
where T: 'static
{
cons_block(move |x: Rc<Transact<T>>| {
release_facility(facility, x.clone())
.map(move |()| x)
.into_process()
})
}
#[inline]
pub fn return_block<T>(facility: Rc<Facility<T>>) -> impl Block<Input = Rc<Transact<T>>, Output = Rc<Transact<T>>>
where T: 'static
{
cons_block(move |x: Rc<Transact<T>>| {
return_facility(facility, x.clone())
.map(move |()| x)
.into_process()
})
}
#[inline]
pub fn preempt_block<T>(facility: Rc<Facility<T>>, mode: PreemptBlockMode<T>) -> impl Block<Input = Rc<Transact<T>>, Output = Rc<Transact<T>>>
where T: 'static
{
cons_block(move |x: Rc<Transact<T>>| {
preempt_facility(facility, x.clone(), mode.into())
.map(move |()| x)
.into_process()
})
}
#[derive(Clone)]
pub struct PreemptBlockMode<T> {
pub priority_mode: bool,
pub transfer: Option<PreemptBlockTransfer<T>>,
pub remove_mode: bool
}
impl<T> From<FacilityPreemptMode<T>> for PreemptBlockMode<T>
where T: 'static
{
fn from(mode: FacilityPreemptMode<T>) -> Self {
let FacilityPreemptMode { priority_mode, transfer, remove_mode } = mode;
let transfer = match transfer {
None => None,
Some(f) => Some({
PreemptBlockTransfer::new(move |dt| {
cons_block(move |transact| {
f.call_box((transact, dt))
}).into_boxed()
})
})
};
PreemptBlockMode {
priority_mode: priority_mode,
transfer: transfer,
remove_mode: remove_mode
}
}
}
pub struct PreemptBlockTransfer<T> {
f: Box<dyn PreemptBlockTransferFnBoxClone<T>>
}
impl<T> PreemptBlockTransfer<T> {
#[inline]
pub fn new<F>(f: F) -> Self
where F: FnOnce(Option<f64>) -> BlockBox<Rc<Transact<T>>, ()> + Clone + 'static
{
PreemptBlockTransfer {
f: Box::new(f)
}
}
#[inline]
pub fn call_box(self, arg: Option<f64>) -> BlockBox<Rc<Transact<T>>, ()> {
let PreemptBlockTransfer { f } = self;
f.call_box(arg)
}
}
impl<T> Clone for PreemptBlockTransfer<T> {
#[inline]
fn clone(&self) -> Self {
PreemptBlockTransfer {
f: self.f.call_clone()
}
}
}
trait PreemptBlockTransferFnBox<T> {
fn call_box(self: Box<Self>, args: Option<f64>) -> BlockBox<Rc<Transact<T>>, ()>;
}
impl<T, F> PreemptBlockTransferFnBox<T> for F
where F: FnOnce(Option<f64>) -> BlockBox<Rc<Transact<T>>, ()>
{
fn call_box(self: Box<Self>, args: Option<f64>) -> BlockBox<Rc<Transact<T>>, ()> {
let this: Self = *self;
this(args)
}
}
trait PreemptBlockTransferFnBoxClone<T>: PreemptBlockTransferFnBox<T> {
fn call_clone(&self) -> Box<dyn PreemptBlockTransferFnBoxClone<T>>;
}
impl<T, F> PreemptBlockTransferFnBoxClone<T> for F
where F: FnOnce(Option<f64>) -> BlockBox<Rc<Transact<T>>, ()> + Clone + 'static
{
fn call_clone(&self) -> Box<dyn PreemptBlockTransferFnBoxClone<T>> {
Box::new(self.clone())
}
}