use crate::common::tsafe::TSafe;
use crate::actors::props::Props;
use crate::actors::actor_path::ActorPath;
use crate::actors::actor_cell::ActorCell;
use crate::actors::actor::PoisonPill;
use crate::actors::default_dispatcher::DefaultDispatcher;
use crate::actors::dead_letters::DeadLetters;
use crate::actors::synthetic_actor::SyntheticActor;
use crate::actors::unbound_mailbox::UnboundMailbox;
use crate::actors::actor_ref_factory::ActorRefFactory;
use crate::actors::abstract_actor_system::AbstractActorSystem;
use crate::testkit::actors::test_local_actor_ref::TestLocalActorRef;
use crate::testkit::actors::test_probe::TestProbe;
use crate::actors::abstract_actor_ref::ActorRef;
use std::sync::{Arc, Mutex};
pub struct TestLocalActorSystem {
nids: usize,
pub dispatcher: TSafe<DefaultDispatcher>,
dead_letters: Option<ActorRef>
}
impl TestLocalActorSystem {
pub fn new() -> TSafe<TestLocalActorSystem> {
let cpu_count = num_cpus::get();
let mut dispatcher = DefaultDispatcher::new(cpu_count as u32);
let dispatcher = tsafe!(dispatcher);
let mut system = TestLocalActorSystem {
nids: 0,
dispatcher: dispatcher.clone(),
dead_letters: None
};
let system = tsafe!(system);
let dlp = tsafe!(ActorPath::new("deadLetters"));
let dlm = DeadLetters::new();
let dlc = ActorCell::new(system.clone(), dlp.clone(),tsafe!(SyntheticActor {}), 0, dispatcher.clone(), tsafe!(dlm));
let boxed_dlc = tsafe!(dlc);
system.lock().unwrap().dead_letters = Some(Box::new(TestLocalActorRef::new(boxed_dlc.clone(), dlp)));
boxed_dlc.lock().unwrap().start(boxed_dlc.clone());
system
}
pub fn create_probe(self: &Self, name: Option<&str>) -> TestProbe {
TestProbe::new(tsafe!(self.clone()), name)
}
}
impl ActorRefFactory for TestLocalActorSystem {
fn actor_of(self: &mut Self, props: Props, name: Option<&str>) -> ActorRef {
let mailbox = tsafe!(UnboundMailbox::new());
let mut aname: String;
if name.is_some() {
aname = name.unwrap().to_string();
} else {
aname = self.nids.to_string();
self.nids = self.nids + 1;
}
let path = tsafe!(ActorPath::new(&aname));
let mut cell = ActorCell::new(
tsafe!(self.clone()),
path.clone(),
props.actor,
0,
self.dispatcher.clone(),
mailbox
);
let boxed_cell = tsafe!(cell);
boxed_cell.lock().unwrap().start(boxed_cell.clone());
Box::new(TestLocalActorRef::new(boxed_cell, path))
}
fn stop(self: &mut Self, aref: &mut ActorRef) {
let aref_cpy0 = aref.clone();
let aref_cpy1 = aref.clone();
let x = aref.cell();
let mut cell = x.lock().unwrap();
cell.suspend();
cell.mailbox.lock().unwrap().clean_up(aref_cpy0, self.dead_letters());
cell.force_send(aref.cell().clone(), Box::new(PoisonPill {}), None, aref_cpy1);
}
fn dead_letters(self: &mut Self) -> ActorRef {
match &self.dead_letters {
Some(d) => {
(*d).clone()
}
_ => panic!("Dead letter is empty")
}
}
}
impl AbstractActorSystem for TestLocalActorSystem {}
impl Clone for TestLocalActorSystem {
fn clone(&self) -> Self {
let dead_letter: Option<ActorRef> = match &self.dead_letters {
Some(v) => Some((*v).clone()),
None => None
};
TestLocalActorSystem {
nids: self.nids,
dispatcher: self.dispatcher.clone(),
dead_letters: dead_letter }
}
}