use std::rc::Rc;
use std::ops::Deref;
use crate::simulation::Point;
use crate::simulation::ref_comp::*;
use dvcompute_utils::collections::im::*;
pub trait QueueStorage {
type Priority;
type Item;
fn is_empty(&self, p: &Point) -> bool;
fn pop(&self, p: &Point) -> Option<Self::Item>;
fn push(&self, item: Self::Item, p: &Point);
fn push_with_priority(&self, priority: Self::Priority, item: Self::Item, p: &Point);
fn remove_by<F>(&self, predicate: F, p: &Point) -> Option<Self::Item>
where F: Fn(&Self::Item) -> bool + Clone;
fn exists<F>(&self, predicate: F, p: &Point) -> bool
where F: Fn(&Self::Item) -> bool + Clone;
fn find<F>(&self, predicate: F, p: &Point) -> Option<Self::Item>
where F: Fn(&Self::Item) -> bool + Clone,
Self::Item: Clone;
}
pub type QueueStorageBox<Item, Priority> = Box<dyn BoxableQueueStorage<Item = Item, Priority = Priority>>;
pub trait BoxableQueueStorage {
type Priority;
type Item;
fn is_empty(&self, p: &Point) -> bool;
fn pop(&self, p: &Point) -> Option<Self::Item>;
fn push(&self, item: Self::Item, p: &Point);
fn push_with_priority(&self, priority: Self::Priority, item: Self::Item, p: &Point);
fn remove_boxed_by(&self, predicate: Rc<dyn Fn(&Self::Item) -> bool>, p: &Point) -> Option<Self::Item>;
fn exists_boxed(&self, predicate: Rc<dyn Fn(&Self::Item) -> bool>, p: &Point) -> bool;
fn find_boxed(&self, predicate: Rc<dyn Fn(&Self::Item) -> bool>, p: &Point) -> Option<Self::Item>
where Self::Item: Clone;
}
impl<S> BoxableQueueStorage for S
where S: QueueStorage
{
type Priority = S::Priority;
type Item = S::Item;
fn is_empty(&self, p: &Point) -> bool {
S::is_empty(self, p)
}
fn pop(&self, p: &Point) -> Option<Self::Item> {
S::pop(self, p)
}
fn push(&self, item: Self::Item, p: &Point) {
S::push(self, item, p)
}
fn push_with_priority(&self, priority: Self::Priority, item: Self::Item, p: &Point) {
S::push_with_priority(self, priority, item, p)
}
fn remove_boxed_by(&self, predicate: Rc<dyn Fn(&Self::Item) -> bool>, p: &Point) -> Option<Self::Item> {
S::remove_by(self, move |x| { predicate(x) }, p)
}
fn exists_boxed(&self, predicate: Rc<dyn Fn(&Self::Item) -> bool>, p: &Point) -> bool {
S::exists(self, move |x| { predicate(x) }, p)
}
fn find_boxed(&self, predicate: Rc<dyn Fn(&Self::Item) -> bool>, p: &Point) -> Option<Self::Item>
where Self::Item: Clone
{
S::find(self, move |x| { predicate(x) }, p)
}
}
pub trait QueueStrategy {
type Priority;
fn new_storage<T>(&self) -> QueueStorageBox<T, Self::Priority>
where T: Clone + 'static;
}
pub struct FCFSStorage<T> {
queue: RefComp<Queue<T>>
}
impl<T> FCFSStorage<T>
where T: Clone
{
pub fn new() -> Self {
FCFSStorage { queue: RefComp::new(Queue::empty()) }
}
}
impl<T> QueueStorage for FCFSStorage<T>
where T: Clone + 'static
{
type Priority = ();
type Item = T;
#[inline]
fn is_empty(&self, p: &Point) -> bool {
let queue = self.queue.read_at(p);
queue.is_empty()
}
fn pop(&self, p: &Point) -> Option<Self::Item> {
let results = {
let queue = self.queue.read_at(p);
queue.pop_front()
};
match results {
None => None,
Some((item, queue)) => {
self.queue.write_at(queue, p);
Some(item)
}
}
}
fn push(&self, item: Self::Item, p: &Point) {
let results = {
let queue = self.queue.read_at(p);
queue.push_back(item)
};
self.queue.write_at(results, p);
}
fn push_with_priority(&self, _priority: Self::Priority, _item: Self::Item, _p: &Point) {
panic!("Not supported operation");
}
fn remove_by<F>(&self, predicate: F, p: &Point) -> Option<Self::Item>
where F: Fn(&Self::Item) -> bool + Clone
{
let results = {
let queue = self.queue.read_at(p);
queue.remove_by(predicate)
};
match results {
None => None,
Some((item, queue)) => {
self.queue.write_at(queue, p);
Some(item)
}
}
}
fn exists<F>(&self, predicate: F, p: &Point) -> bool
where F: Fn(&Self::Item) -> bool + Clone
{
let queue = self.queue.read_at(p);
queue.exists(predicate)
}
fn find<F>(&self, predicate: F, p: &Point) -> Option<T>
where F: Fn(&Self::Item) -> bool + Clone,
Self::Item: Clone
{
let queue = self.queue.read_at(p);
queue.find(predicate)
}
}
pub struct LCFSStorage<T> {
queue: RefComp<List<T>>
}
impl<T> LCFSStorage<T>
where T: Clone
{
pub fn new() -> Self {
LCFSStorage { queue: RefComp::new(List::Nil) }
}
}
impl<T> QueueStorage for LCFSStorage<T>
where T: Clone + 'static
{
type Priority = ();
type Item = T;
#[inline]
fn is_empty(&self, p: &Point) -> bool {
let queue = self.queue.read_at(p);
queue.is_empty()
}
fn pop(&self, p: &Point) -> Option<Self::Item> {
match self.queue.read_at(p) {
List::Nil => None,
List::Cons(head, tail) => {
let tail = tail.deref();
self.queue.write_at(tail.clone(), p);
Some(head)
}
}
}
fn push(&self, item: Self::Item, p: &Point) {
let results = {
let queue = self.queue.read_at(p);
List::Cons(item, Rc::new(queue))
};
self.queue.write_at(results, p);
}
fn push_with_priority(&self, _priority: Self::Priority, _item: Self::Item, _p: &Point) {
panic!("Not supported operation");
}
fn remove_by<F>(&self, predicate: F, p: &Point) -> Option<Self::Item>
where F: Fn(&Self::Item) -> bool + Clone
{
let results = {
let queue = self.queue.read_at(p);
queue.remove_by(predicate)
};
match results {
None => None,
Some((item, queue)) => {
self.queue.write_at(queue, p);
Some(item)
}
}
}
fn exists<F>(&self, predicate: F, p: &Point) -> bool
where F: Fn(&Self::Item) -> bool + Clone
{
let queue = self.queue.read_at(p);
queue.exists(predicate)
}
fn find<F>(&self, predicate: F, p: &Point) -> Option<T>
where F: Fn(&Self::Item) -> bool + Clone,
Self::Item: Clone
{
let queue = self.queue.read_at(p);
queue.find(predicate)
}
}
#[derive(Clone)]
pub enum FCFSStrategy {
Instance
}
impl QueueStrategy for FCFSStrategy {
type Priority = ();
fn new_storage<T>(&self) -> QueueStorageBox<T, Self::Priority>
where T: Clone + 'static
{
Box::new(FCFSStorage::new())
}
}
#[derive(Clone)]
pub enum LCFSStrategy {
Instance
}
impl QueueStrategy for LCFSStrategy {
type Priority = ();
fn new_storage<T>(&self) -> QueueStorageBox<T, Self::Priority>
where T: Clone + 'static
{
Box::new(LCFSStorage::new())
}
}