diff --git a/src/address.rs b/src/address.rs index 3699cd54..9435b1ab 100644 --- a/src/address.rs +++ b/src/address.rs @@ -1,7 +1,7 @@ //! An address to an actor is a way to send it a message. An address allows an actor to be sent any //! kind of message that it can receive. -use std::fmt::{self, Display, Formatter}; +use std::fmt::{self, Debug, Display, Formatter}; use std::future::Future; use std::{cmp::Ordering, error::Error, hash::Hash}; @@ -44,6 +44,14 @@ pub struct Address { pub(crate) ref_counter: Rc, } +impl Debug for Address { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct(&format!("Address<{}>", std::any::type_name::())) + .field("ref_counter", &self.ref_counter) + .finish() + } +} + /// A `WeakAddress` is a reference to an actor through which [`Message`s](../trait.Message.html) can be /// sent. It can be cloned. Unlike [`Address`](struct.Address.html), a `WeakAddress` will not inhibit /// the dropping of an actor. It is created by the [`Address::downgrade`](struct.Address.html#method.downgrade) diff --git a/src/message_channel.rs b/src/message_channel.rs index 9d2ad186..8c962c8d 100644 --- a/src/message_channel.rs +++ b/src/message_channel.rs @@ -2,6 +2,8 @@ //! any actor that can handle it. It is like [`Address`](../address/struct.Address.html), but associated with //! the message type rather than the actor type. +use std::fmt::Debug; + use futures_core::future::BoxFuture; use futures_core::stream::BoxStream; @@ -77,10 +79,9 @@ use crate::{Handler, KeepRunning}; /// }) /// } /// ``` -pub trait MessageChannel: Sealed + Unpin + Send + Sync { +pub trait MessageChannel: Sealed + Unpin + Debug + Send + Sync { /// The return value of the handler for `M`. type Return: Send + 'static; - /// Returns whether the actor referred to by this address is running and accepting messages. fn is_connected(&self) -> bool; diff --git a/src/refcount.rs b/src/refcount.rs index 0603191c..e883cf1e 100644 --- a/src/refcount.rs +++ b/src/refcount.rs @@ -1,10 +1,9 @@ -use crate::drop_notice; -use crate::drop_notice::DropNotice; +use crate::drop_notice::{self, DropNotice}; +use crate::private::Sealed; +use std::fmt::{Debug, Formatter}; use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, RwLock, Weak as ArcWeak}; -use crate::private::Sealed; - /// The reference count of a strong address. Strong addresses will prevent the actor from being /// dropped as long as they live. Read the docs of [`Address`](../address/struct.Address.html) to find /// out more. @@ -18,6 +17,16 @@ pub struct Strong { lock: Arc>, } +impl Debug for Strong { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Strong") + .field("connected", &self.is_connected()) + .field("strong_count", &self.strong_count()) + .field("weak_count", &self.weak_count()) + .finish() + } +} + #[doc(hidden)] pub struct Shared { connected: AtomicBool, @@ -35,6 +44,10 @@ impl Strong { } } + fn weak_count(&self) -> usize { + Arc::weak_count(&self.shared) + } + pub(crate) fn downgrade(&self) -> Weak { Weak { shared: Arc::downgrade(&self.shared), @@ -55,6 +68,16 @@ pub struct Weak { lock: Arc>, } +impl Debug for Weak { + fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { + f.debug_struct("Weak") + .field("connected", &self.is_connected()) + .field("strong_count", &self.strong_count()) + .field("weak_count", &self.weak_count()) + .finish() + } +} + impl Weak { pub(crate) fn upgrade(&self) -> Option { ArcWeak::upgrade(&self.shared).map(|shared| Strong { @@ -62,10 +85,14 @@ impl Weak { lock: self.lock.clone(), }) } + + fn weak_count(&self) -> usize { + ArcWeak::weak_count(&self.shared) + } } /// A reference counter that can be dynamically either strong or weak. -#[derive(Clone)] +#[derive(Clone, Debug)] pub enum Either { /// A strong reference counter. Strong(Strong), @@ -87,7 +114,7 @@ impl Either { /// [`Strong`](struct.Weak.html). These can be provided as the second type argument to /// [`Address`](../address/struct.Address.html) in order to change how the address affects the actor's /// dropping. Read the docs of [`Address`](../address/struct.Address.html) to find out more. -pub trait RefCounter: Sealed + Clone + Unpin + Send + Sync + 'static { +pub trait RefCounter: Sealed + Clone + Unpin + Debug + Send + Sync + 'static { #[doc(hidden)] fn is_connected(&self) -> bool; #[doc(hidden)] diff --git a/tests/basic.rs b/tests/basic.rs index 1ca3de08..09648048 100644 --- a/tests/basic.rs +++ b/tests/basic.rs @@ -273,3 +273,25 @@ async fn address_send_exercises_backpressure() { .now_or_never() .expect("be able to queue another message because the mailbox is empty again"); } + +#[test] +fn address_debug() { + let (addr1, _ctx) = Context::::new(None); + + let addr2 = addr1.clone(); + let weak_addr = addr2.downgrade(); + + assert_eq!( + format!("{:?}", addr1), + "Address { \ + ref_counter: Strong { connected: true, strong_count: 2, weak_count: 2 } }" + ); + + assert_eq!(format!("{:?}", addr1), format!("{:?}", addr2)); + + assert_eq!( + format!("{:?}", weak_addr), + "Address { \ + ref_counter: Weak { connected: true, strong_count: 2, weak_count: 2 } }" + ); +}