Skip to main content

acktor/
utils.rs

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/// Logs at info level only in debug mode.
11#[doc(hidden)]
12#[macro_export]
13macro_rules! __debug_info {
14    ($($arg:tt)+) => {
15        #[cfg(debug_assertions)]
16        tracing::info!($($arg)+);
17    };
18}
19
20/// Logs at trace level only in debug mode.
21#[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/// Maximum value `create_actor_id` may return. The MSB of the u64 actor id is reserved.
38#[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    // in practice 2^63 actors is impossible to reach, so only a debug assertion here
45    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
71/// Terminates an actor by sending it a [`Signal::Terminate`] message and awaiting its
72/// [`JoinHandle`].
73pub 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}