use crate::actors::abstract_actor_ref::ActorRef;
use crate::actors::actor_path::ActorPath;
use crate::actors::message::Message;
use std::collections::HashMap;
use std::sync::{Mutex, Arc};
pub enum WatchingEvents {
Terminated
}
pub mod events {
pub struct Terminated {}
}
pub struct Watcher {
feed: HashMap<ActorPath, (ActorRef, Vec<ActorRef>)>,
watchers: HashMap<ActorPath, u32>
}
impl Watcher {
pub fn new() -> Watcher {
Watcher {
feed: HashMap::new(),
watchers: HashMap::new()
}
}
pub fn watch(&mut self, watcher: &ActorRef, observed: &ActorRef) {
trace!("{} watch {}", watcher, observed);
let obs_path = observed.path().clone();
if self.feed.contains_key(&obs_path) {
let (_, watchers) = self.feed.get_mut(&obs_path).unwrap();
watchers.push((*watcher).clone());
} else {
self.feed.insert(obs_path, ((*observed).clone(), vec![(*watcher).clone()]));
}
let wt_path = watcher.path();
if self.watchers.contains_key(&wt_path) {
let counter = self.watchers.get_mut(&wt_path).unwrap();
*counter = *counter + 1;
} else {
self.watchers.insert(wt_path, 1);
}
}
pub fn unwatch(&mut self, watcher: &ActorRef, observed: &ActorRef) {
trace!("{} unwatch {}", watcher, observed);
let obs_path = observed.path().clone();
if self.feed.contains_key(&obs_path) {
let (_, watchers) = self.feed.get_mut(&obs_path).unwrap();
let mut new: Vec<ActorRef> = Vec::new();
let wat_path = watcher.path();
for w in watchers.iter() {
if w.path() != wat_path {
new.push((*w).clone());
}
}
if new.len() > 0 {
*watchers = new;
} else {
self.feed.remove(&obs_path);
}
}
let wt_path = watcher.path();
if self.watchers.contains_key(&wt_path) {
let counter = self.watchers.get_mut(&wt_path).unwrap();
*counter = *counter - 1;
if *counter <= 0 {
self.watchers.remove(&wt_path);
}
}
}
pub fn register_event(&mut self, from: &ActorRef, event: WatchingEvents) {
let obs_path = from.path().clone();
match event {
WatchingEvents::Terminated => {
trace!("Registered event 'Terminated' from {}", from);
if self.feed.contains_key(&obs_path) {
let (observed, watchers) =
self.feed.get_mut(&obs_path).unwrap();
for aref in watchers {
trace!("Send Terminated event message from {} to {}", from, aref);
aref.tell(msg!(events::Terminated {}), Some(&observed))
}
self.feed.remove(&obs_path);
}
let wt_path = from.path();
if self.watchers.contains_key(&wt_path) {
warn!("At the time of termination actor {} is subscribed for some events. You must prefer controlled unwatch!", from);
let mut fnv = Vec::new();
for (_, (obs, _)) in self.feed.iter_mut() {
fnv.push(obs.clone());
}
for obs in fnv {
self.unwatch(from, &obs);
}
}
}
}
}
}