use std::fmt::{self, Debug};
use std::sync::Arc;
use ahash::RandomState;
use dashmap::{DashMap, Entry};
use acktor::{Recipient, Sender, SenderId};
use crate::remote_message::RemoteMessage;
#[derive(Clone, Default)]
pub struct RemoteActorRegistry {
inner: Arc<DashMap<u64, Recipient<RemoteMessage>, RandomState>>,
}
impl Debug for RemoteActorRegistry {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
let mut list = f.debug_list();
for entry in self.inner.iter() {
list.entry(entry.key());
}
list.finish()
}
}
impl RemoteActorRegistry {
pub fn new() -> Self {
Self::default()
}
pub fn with_capacity(capacity: usize) -> Self {
Self {
inner: Arc::new(DashMap::with_capacity_and_hasher(
capacity,
RandomState::new(),
)),
}
}
pub fn capacity(&self) -> usize {
self.inner.capacity()
}
pub fn len(&self) -> usize {
self.inner.len()
}
pub fn is_empty(&self) -> bool {
self.inner.is_empty()
}
pub fn retain<F>(&self, mut predicate: F)
where
F: FnMut(u64, &Recipient<RemoteMessage>) -> bool,
{
self.inner
.retain(|index, recipient| predicate(*index, recipient));
}
pub fn get(&self, index: u64) -> Option<Recipient<RemoteMessage>> {
match self.inner.entry(index) {
Entry::Occupied(entry) => {
let recipient = entry.get();
if recipient.is_closed() {
entry.remove();
None
} else {
Some(recipient.clone())
}
}
Entry::Vacant(_) => None,
}
}
pub fn contains_index(&self, index: u64) -> bool {
match self.inner.entry(index) {
Entry::Occupied(entry) => {
if entry.get().is_closed() {
entry.remove();
false
} else {
true
}
}
Entry::Vacant(_) => false,
}
}
pub fn remove(&self, index: u64) -> Option<Recipient<RemoteMessage>> {
self.inner.remove(&index).map(|(_, recipient)| recipient)
}
pub fn insert<A>(&self, actor: A) -> bool
where
A: Into<Recipient<RemoteMessage>> + SenderId,
{
let index = actor.index();
match self.inner.entry(index) {
Entry::Occupied(_) => false,
Entry::Vacant(entry) => {
entry.insert(actor.into());
true
}
}
}
}