1use std::any::Any;
2use std::sync::atomic::{AtomicU64, Ordering};
3
4use tracing::{debug, warn};
5
6use crate::actor::{ActorId, JoinHandle};
7use crate::address::{Recipient, Sender, SenderId};
8use crate::signal::Signal;
9
10#[doc(hidden)]
12#[macro_export]
13macro_rules! __debug_info {
14 ($($arg:tt)+) => {
15 #[cfg(debug_assertions)]
16 tracing::info!($($arg)+);
17 };
18}
19
20#[doc(hidden)]
22#[macro_export]
23macro_rules! __debug_trace {
24 ($($arg:tt)+) => {
25 #[cfg(debug_assertions)]
26 tracing::trace!($($arg)+);
27 };
28}
29
30#[doc(inline)]
31pub use crate::__debug_info as debug_info;
32#[doc(inline)]
33pub use crate::__debug_trace as debug_trace;
34
35static ACTOR_ID_ALLOCATOR: AtomicU64 = AtomicU64::new(0);
36
37#[doc(hidden)]
39pub const MAX_ACTOR_ID: u64 = (1 << 63) - 1;
40
41#[inline]
42pub(crate) fn create_actor_id() -> ActorId {
43 let id = ACTOR_ID_ALLOCATOR.fetch_add(1, Ordering::Relaxed);
44 debug_assert!(
46 id <= MAX_ACTOR_ID,
47 "actor id space exhausted (more than {} actors allocated in the current process)",
48 MAX_ACTOR_ID
49 );
50 id
51}
52
53#[inline]
54pub(crate) fn panic_info_to_string(info: &(dyn Any + Send)) -> String {
55 if let Some(s) = info.downcast_ref::<&str>() {
56 s.to_string()
57 } else if let Some(s) = info.downcast_ref::<String>() {
58 s.clone()
59 } else {
60 "could not capture the panic info".to_string()
61 }
62}
63
64#[doc(hidden)]
65#[inline]
66pub fn type_name<T>() -> &'static str {
67 let type_name = std::any::type_name::<T>().split("<").next().unwrap();
68 type_name.rsplit("::").next().unwrap()
69}
70
71pub async fn terminate_actor<A>(address: A, join_handle: JoinHandle<()>)
74where
75 A: Into<Recipient<Signal>>,
76{
77 let address = address.into();
78 if let Err(e) = address.do_send(Signal::Terminate).await {
79 warn!("Could not stop actor {}: {}", address.index(), e);
80 join_handle.abort();
81 }
82 debug!("Waiting for actor {} to stop", address.index());
83 let _ = join_handle.await;
84}