use std::any::{Any, TypeId};
use std::cell::RefCell;
use std::collections::HashMap;
use std::default::Default;
use std::sync::{Arc, Mutex};
use actor::{Actor, Supervised};
use arbiter::Arbiter;
use address::{Addr, Syn, Unsync};
use context::Context;
use supervisor::Supervisor;
pub struct Registry {
registry: RefCell<HashMap<TypeId, Box<Any>>>,
}
#[allow(unused_variables)]
pub trait ArbiterService: Actor<Context=Context<Self>> + Supervised + Default {
fn service_started(&mut self, ctx: &mut Context<Self>) {}
fn from_registry() -> Addr<Unsync, Self> {
Arbiter::registry().get::<Self>()
}
}
#[allow(unused_variables)]
pub trait SystemService: Actor<Context=Context<Self>> + Supervised + Default {
fn service_started(&mut self, ctx: &mut Context<Self>) {}
fn from_registry() -> Addr<Syn, Self> {
Arbiter::system_registry().get::<Self>()
}
}
impl Registry {
pub(crate) fn new() -> Self {
Registry{registry: RefCell::new(HashMap::new())}
}
pub fn get<A: ArbiterService + Actor<Context=Context<A>>>(&self) -> Addr<Unsync, A> {
let id = TypeId::of::<A>();
if let Some(addr) = self.registry.borrow().get(&id) {
if let Some(addr) = addr.downcast_ref::<Addr<Unsync, A>>() {
return addr.clone()
}
}
let addr: Addr<Unsync, A> = Supervisor::start(|ctx| {
let mut act = A::default();
act.service_started(ctx);
act
});
self.registry.borrow_mut().insert(id, Box::new(addr.clone()));
addr
}
}
pub struct SystemRegistry {
registry: Arc<Mutex<HashMap<TypeId, Box<Any>>>>,
}
unsafe impl Send for SystemRegistry {}
impl SystemRegistry {
pub(crate) fn new() -> Self {
SystemRegistry{registry: Arc::new(Mutex::new(HashMap::new()))}
}
pub fn get<A: SystemService + Actor<Context=Context<A>>>(&self) -> Addr<Syn,A> {
{
if let Ok(hm) = self.registry.lock() {
if let Some(addr) = hm.get(&TypeId::of::<A>()) {
match addr.downcast_ref::<Addr<Syn, A>>() {
Some(addr) => {
return addr.clone()
},
None => error!("Got unknown value: {:?}", addr),
}
}
} else { panic!("System registry lock is poisoned"); }
}
let addr = Supervisor::start_in(&Arbiter::system_arbiter(), |ctx| {
let mut act = A::default();
act.service_started(ctx);
act
});
if let Ok(mut hm) = self.registry.lock() {
hm.insert(TypeId::of::<A>(), Box::new(addr.clone()));
return addr
}
panic!("System registry lock is poisoned");
}
}
impl Clone for SystemRegistry {
fn clone(&self) -> Self {
SystemRegistry{registry: Arc::clone(&self.registry)}
}
}