use std::rc::{Rc,Weak};
use std::cell::RefCell;
use std::mem::{size_of};
use crate::{Phit,Simulation};
use crate::topology::Location;
use crate::quantify::Quantifiable;
use crate::router::{AcknowledgeMessage};
use quantifiable_derive::Quantifiable;
pub trait Eventful
{
fn process(&mut self, simulation:&Simulation) -> Vec<EventGeneration>;
fn pending_events(&self)->usize;
fn add_pending_event(&mut self);
fn clear_pending_events(&mut self);
fn as_eventful(&self)->Weak<RefCell<dyn Eventful>>;
}
#[derive(Clone)]
pub enum Event
{
PhitToLocation{
phit: Rc<Phit>,
previous: Location,
new: Location,
},
Acknowledge{
location: Location,
message: AcknowledgeMessage,
},
Generic(Rc<RefCell<dyn Eventful>>),
}
impl Quantifiable for Event
{
fn total_memory(&self) -> usize
{
let mut total= size_of::<Self>();
match self
{
&Event::PhitToLocation{
ref phit,
previous: _,
new: _,
} => total+=phit.as_ref().total_memory(),
_ => (),
}
total
}
fn print_memory_breakdown(&self)
{
unimplemented!();
}
fn forecast_total_memory(&self) -> usize
{
unimplemented!();
}
}
pub enum CyclePosition
{
Begin,
End,
}
pub struct EventGeneration
{
pub delay: usize,
pub position: CyclePosition,
pub event: Event,
}
#[derive(Quantifiable)]
pub struct EventQueue
{
event_begin_circle: Vec<Vec<Event>>, event_end_circle: Vec<Vec<Event>>, current: usize,
}
impl EventQueue
{
pub fn new (size:usize) -> EventQueue
{
EventQueue{
event_begin_circle: vec![ vec![] ; size ],
event_end_circle: vec![ vec![] ; size ],
current:0,
}
}
pub fn advance(&mut self)
{
self.event_begin_circle[self.current]=Vec::new();
self.event_end_circle[self.current]=Vec::new();
self.current=(self.current+1)%self.event_begin_circle.len();
}
pub fn access_begin(&self, ievent:usize) -> Option<&Event>
{
let v=&self.event_begin_circle[self.current];
if ievent<v.len()
{
Some(&v[ievent])
}
else
{
None
}
}
pub fn access_end(&self, ievent:usize) -> Option<&Event>
{
let v=&self.event_end_circle[self.current];
if ievent<v.len()
{
Some(&v[ievent])
}
else
{
None
}
}
pub fn enqueue_begin(&mut self, event:Event, delay: usize)
{
if delay>=self.event_begin_circle.len()
{
panic!("Delay too long");
}
let position=(self.current+delay)%self.event_begin_circle.len();
self.event_begin_circle[position].push(event);
}
pub fn enqueue_end(&mut self, event:Event, delay: usize)
{
if delay>=self.event_end_circle.len()
{
panic!("Delay too long");
}
let position=(self.current+delay)%self.event_end_circle.len();
self.event_end_circle[position].push(event);
}
pub fn enqueue(&mut self, event_generation:EventGeneration)
{
match event_generation.position
{
CyclePosition::Begin => self.enqueue_begin(event_generation.event,event_generation.delay),
CyclePosition::End => self.enqueue_end(event_generation.event,event_generation.delay),
};
}
}