nautilus_common/actor/
registry.rs1use std::{
17 cell::{RefCell, UnsafeCell},
18 fmt::Debug,
19 rc::Rc,
20 sync::OnceLock,
21};
22
23use ahash::{HashMap, HashMapExt};
24use ustr::Ustr;
25
26use super::Actor;
27
28pub struct ActorRegistry {
29 actors: RefCell<HashMap<Ustr, Rc<UnsafeCell<dyn Actor>>>>,
30}
31
32impl Debug for ActorRegistry {
33 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
34 let actors_ref = self.actors.borrow();
35 let keys: Vec<&Ustr> = actors_ref.keys().collect();
36 f.debug_struct(stringify!(ActorRegistry))
37 .field("actors", &keys)
38 .finish()
39 }
40}
41
42impl Default for ActorRegistry {
43 fn default() -> Self {
44 Self::new()
45 }
46}
47
48impl ActorRegistry {
49 pub fn new() -> Self {
50 Self {
51 actors: RefCell::new(HashMap::new()),
52 }
53 }
54
55 pub fn insert(&self, id: Ustr, actor: Rc<UnsafeCell<dyn Actor>>) {
56 self.actors.borrow_mut().insert(id, actor);
57 }
58
59 pub fn get(&self, id: &Ustr) -> Option<Rc<UnsafeCell<dyn Actor>>> {
60 self.actors.borrow().get(id).cloned()
61 }
62}
63
64unsafe impl Sync for ActorRegistry {}
69unsafe impl Send for ActorRegistry {}
70
71static ACTOR_REGISTRY: OnceLock<ActorRegistry> = OnceLock::new();
72
73pub fn get_actor_registry() -> &'static ActorRegistry {
74 ACTOR_REGISTRY.get_or_init(ActorRegistry::new)
75}
76
77pub fn register_actor(actor: Rc<UnsafeCell<dyn Actor>>) {
78 let actor_id = unsafe { &*actor.get() }.id();
81 get_actor_registry().insert(actor_id, actor);
82}
83
84pub fn get_actor(id: &Ustr) -> Option<Rc<UnsafeCell<dyn Actor>>> {
85 get_actor_registry().get(id)
86}
87
88#[allow(clippy::mut_from_ref)]
94pub fn get_actor_unchecked<T: Actor>(id: &Ustr) -> &mut T {
95 let actor = get_actor(id).unwrap_or_else(|| panic!("Actor for {id} not found"));
96 unsafe { &mut *(actor.get() as *mut _ as *mut T) }
97}
98
99#[cfg(test)]
101pub fn clear_actor_registry() {
102 get_actor_registry().actors.borrow_mut().clear();
104}