Skip to content

Instantly share code, notes, and snippets.

@max6cn
Last active August 7, 2019 17:57
Show Gist options
  • Save max6cn/8e42cacffecfce07920f6fecba936dad to your computer and use it in GitHub Desktop.
Save max6cn/8e42cacffecfce07920f6fecba936dad to your computer and use it in GitHub Desktop.
Q Framework
pub struct Context<'a , T = i32>{
simulator: *mut Simulator,
servers : *mut Server,
generator: *mut Generator,
events: *mut EventQueue,
queue: *mut Queue,
_marker: PhantomData<&'a T>,
}
impl <'a, T> Context<'a, T>{
pub fn get_simulator(&self) -> &'a mut Simulator {
let ptr = unsafe { &mut *self.simulator };
ptr
}
pub fn get_servers(&self) -> &'a mut Server {
let ptr = unsafe { &mut *self.servers };
ptr
}
pub fn get_generator(&self) -> &'a mut Generator {
let ptr = unsafe { &mut *self.generator };
ptr
}
pub fn get_events(&self) -> &'a mut EventQueue {
let ptr = unsafe { &mut *self.events };
ptr
}
pub fn get_queue(&self) -> &'a mut Queue {
let ptr = unsafe { &mut *self.queue };
ptr
}
}
pub struct Event {
id: EventId,
clock: Clock,
etype: EventType
}
//
// Explicitly implement the trait so the queue becomes a min-heap instead of a max-heap.
impl Ord for Event {
fn cmp(&self, other: &Self) -> Ordering {
other.clock.cmp(&self.clock)
}
}
impl PartialOrd for Event {
fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
Some(other.get_clock().cmp(&self.get_clock()))
}
}
impl PartialEq for Event {
fn eq(&self, other: &Self) -> bool {
self.get_clock() == other.get_clock()
}
}
impl Eq for Event {
}
impl AbstractEvent for Event {
fn execute(&mut self, ctx : &mut Context) {
// info!("Running Event");
match self.etype {
EventType::ServerEvent => {
trace!("Running Server");
let mut server = ctx.get_servers();
server.execute(ctx);
},
EventType::GeneratorEvent =>{
trace!("Running Generator");
let mut generator = ctx.get_generator();
generator.execute(ctx);
}
}
}
}
impl Clocked for Event{
fn get_clock(&self) -> Clock {
self.clock
}
fn set_clock(&mut self, t: Clock) {
self.clock = t;
}
}
impl Event{
pub fn new( etype: EventType, clock: Clock) -> Self{
let id = 0;
Event {id, clock, etype}
}
}
pub struct Generator {
max_sim_time: Clock,
clock: Clock,
pub count: u64,
}
impl AbstractEvent for Generator {
fn execute(&mut self, ctx: &mut Context) {
let customer = Customer::new(self.count);
info!("{:?} generated {:?}", self.get_clock(), customer);
let mut queue = ctx.get_queue();
queue.insert(ctx, customer);
self.count += 1;
self.clock = 1+ self.clock;
if self.get_clock() < self.max_sim_time {
let event = Event::new(EventType::GeneratorEvent, self.get_clock());
ctx.get_events().insert(event);
}
}
}
impl Clocked for Generator {
fn get_clock(&self) -> Clock {
self.clock
}
fn set_clock(&mut self, t: Clock) {
self.clock = t;
}
}
impl Generator {
pub fn new( max_sim_time: Clock ) -> Self {
Generator { max_sim_time, clock: Clock::from(0), count: 0 }
}
}
pub struct Queue{
customers: Vec<Customer>,
pub capacity: usize,
}
impl Queue {
pub fn new() -> Self {
return Queue {customers: Default::default(), capacity: 10};
}
pub fn size(&self) -> usize {
self.customers.len()
}
pub fn insert( &mut self, ctx: &mut Context, customer: Customer) {
let mut server = ctx.get_servers();
let mut sim = ctx.get_simulator();
let t = sim.get_clock();
if server.is_available() {
server.insert( ctx, Some(customer));
} else if self.customers.len() >= self.capacity {
info!("{:?} rejected {:?}", server.get_clock(), customer) ;
} else {
self.customers.push(customer);
trace!("adding customer {:?}", customer);
}
}
pub fn remove(&mut self) -> Option<Customer>{
self.customers.pop()
}
}
pub struct Server {
pub total_customers_servered :i32,
pub customer_being_served : Option<Customer>,
clock: Clock
}
impl Clocked for Server {
fn get_clock(&self) -> Clock {
self.clock
}
fn set_clock(&mut self, t: Clock) {
self.clock = t;
}
}
impl Server {
pub fn is_available(&self) -> bool {
self.customer_being_served.is_none()
}
pub fn new() -> Self {
Server { total_customers_servered: Default::default(),
customer_being_served: Default::default(),
clock: Clock::from(0)}
}
pub fn insert( &mut self, ctx: &mut Context, customer: Option<Customer>) {
if self.customer_being_served.is_some() {
return;
} else {
self.customer_being_served = customer;
self.clock = self.clock + 1;
let event = Event::new(EventType::ServerEvent, self.get_clock());
ctx.get_events().insert(event);
}
}
}
impl AbstractEvent for Server {
fn execute( &mut self, ctx: &mut Context ){
let c = self.customer_being_served.take();
self.total_customers_servered += 1;
info!("{:?} serving {:?} \ttotal served {:?}", self.get_clock(), c, self.total_customers_servered);
let q = ctx.get_queue();
if let Some(c) = q.remove() {
self.insert(ctx, Some(c) );
}
}
}
impl Clocked for Simulator {
fn get_clock(&self) -> Clock {
self.clock
}
fn set_clock(&mut self, t: Clock) {
self.clock = t;
}
}
impl Simulator {
pub fn new() -> Simulator {
Simulator { clock: Clock::from(0)}
}
}
pub fn do_all_events(ctx: &mut Context) -> (i64,i64,f64) {
loop {
let event = ctx.get_events().remove_first();
match event {
Some(mut e) => {
let t = e.get_clock() ;
ctx.get_simulator().set_clock(t);
e.execute( ctx);
}
_ => {
info!("{:?} Finished All Events",ctx.get_simulator().get_clock());
break;
}
}
}
(ctx.get_generator().count as i64,
ctx.get_servers().total_customers_servered as i64,
ctx.get_simulator().get_clock().get_raw())
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment