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 address::{Addr, Syn, Unsync};
use arbiter::Arbiter;
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>()
}
fn init_actor<F>(f: F) -> Addr<Unsync, Self> where F: FnOnce(&mut Self::Context) -> Self + 'static{
Arbiter::registry().init_actor::<Self, F>(f)
}
}
#[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>()
}
fn init_actor<F>(f: F) -> Addr<Syn, Self> where F: FnOnce(&mut Self::Context) -> Self + Send + 'static{
Arbiter::system_registry().init_actor::<Self, F>(f)
}
}
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 fn init_actor<A: ArbiterService + Actor<Context=Context<A>>, F>(&self, with: F) -> Addr<Unsync, A> where F: FnOnce(&mut A::Context) -> A + 'static {
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 = with(ctx);
act.service_started(ctx);
act
});
self.registry.borrow_mut().insert(id, Box::new(addr.clone()));
addr
}
pub fn set<A: ArbiterService + Actor<Context=Context<A>>>(&self, addr: Addr<Unsync, A>) {
let id = TypeId::of::<A>();
if let Some(addr) = self.registry.borrow().get(&id) {
match addr.downcast_ref::<Addr<Unsync, A>>() {
Some(_) => {
panic!("Actor already started")
},
None => {},
}
}
self.registry.borrow_mut().insert(id, Box::new(addr.clone()));
}
}
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");
}
pub fn init_actor<A: SystemService + Actor<Context=Context<A>>, F>(&self, with: F) -> Addr<Syn,A> where F: FnOnce(&mut A::Context) -> A + Send + 'static {
let addr = Supervisor::start_in(&Arbiter::system_arbiter(), |ctx| {
let mut act = with(ctx);
act.service_started(ctx);
act
});
self.set(addr.clone());
addr
}
pub fn set<A: SystemService + Actor<Context=Context<A>>>(&self, addr: 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(_) => {
panic!("Actor already started")
},
None => {},
}
}
} else { panic!("System registry lock is poisoned"); }
}
if let Ok(mut hm) = self.registry.lock() {
hm.insert(TypeId::of::<A>(), Box::new(addr.clone()));
} else {
panic!("System registry lock is poisoned");
}
}
}
impl Clone for SystemRegistry {
fn clone(&self) -> Self {
SystemRegistry{registry: Arc::clone(&self.registry)}
}
}