use crate::common::tsafe::TSafe;
use crate::actors::abstract_actor_system::AbstractActorSystem;
use crate::actors::message::Message;
use crate::actors::scheduler::TaskGuard;
use crate::actors::abstract_actor_ref::ActorRef;
use std::collections::HashMap;
use std::time::Duration;
use std::sync::mpsc::channel;
pub type Timers = Box<AbstractTimers + Send>;
pub trait AbstractTimers {
fn start_single(&mut self, key: u32, self_: &ActorRef, to: &ActorRef, delay: Duration, msg: Message);
fn start_periodic(&mut self, key: u32, self_: &ActorRef, to: &ActorRef, interval: Duration, msg: Box<'static + Fn() -> Message + Send>);
fn cancel(&mut self, key: u32);
fn cancel_all(&mut self);
}
pub struct RealTimers {
system: TSafe<AbstractActorSystem + Send>,
tasks: HashMap<u32, TaskGuard>
}
impl RealTimers {
pub fn new(system: TSafe<AbstractActorSystem + Send>) -> Timers {
let r = RealTimers {
system,
tasks: HashMap::new()
};
Box::new(r)
}
}
impl AbstractTimers for RealTimers {
fn start_single(&mut self, key: u32, self_: &ActorRef, to: &ActorRef, delay: Duration, msg: Message)
{
let (msg_sender, msg_receiver) = channel();
let (self_sender, self_receiver) = channel();
let (to_sender, to_receiver) = channel();
let scheduler = self.system.lock().unwrap().get_scheduler();
let guard = scheduler.lock().unwrap().schedule_once(delay,move || {
let msg = msg_receiver.recv().unwrap();
let self_ = self_receiver.recv().unwrap();
let mut to: ActorRef = to_receiver.recv().unwrap();
to.tell(msg, Some(&self_));
});
self.tasks.insert(key, guard);
msg_sender.send(msg);
self_sender.send((*self_).clone());
to_sender.send((*to).clone());
}
fn start_periodic(&mut self, key: u32, self_: &ActorRef, to: &ActorRef, interval: Duration, msg: Box<'static + Fn() -> Message + Send>)
{
let (msg_sender, msg_receiver) = channel();
let (self_sender, self_receiver) = channel();
let (to_sender, to_receiver) = channel();
let msg_sender_clone = msg_sender.clone();
let self_sender_clone = self_sender.clone();
let to_sender_clone = to_sender.clone();
let scheduler = self.system.lock().unwrap().get_scheduler();
let guard = scheduler.lock().unwrap().schedule_periodic(interval,move || {
let msg: Box<'static + Fn() -> Message + Send> = msg_receiver.recv().unwrap();
let self_: ActorRef = self_receiver.recv().unwrap();
let mut to: ActorRef = to_receiver.recv().unwrap();
to.tell(msg(), Some(&self_));
msg_sender_clone.send(msg);
self_sender_clone.send(self_);
to_sender_clone.send(to);
});
self.tasks.insert(key, guard);
msg_sender.send(msg);
self_sender.send((*self_).clone());
to_sender.send((*to).clone());
}
fn cancel(&mut self, key: u32) {
self.tasks.remove(&key);
}
fn cancel_all(&mut self) {
self.tasks.clear();
}
}
pub struct StubTimers {}
impl StubTimers {
pub fn new() -> Timers {
Box::new(StubTimers {})
}
}
impl AbstractTimers for StubTimers {
fn start_single(&mut self, key: u32, self_: &ActorRef, to: &ActorRef, delay: Duration, msg: Message) {
unimplemented!()
}
fn start_periodic(&mut self, key: u32, self_: &ActorRef, to: &ActorRef, interval: Duration, msg: Box<'static + Fn() -> Message + Send>)
{
unimplemented!()
}
fn cancel(&mut self, key: u32) {}
fn cancel_all(&mut self) {}
}