Skip to content

Commit

Permalink
Add a debug implementation for Address (#67)
Browse files Browse the repository at this point in the history
* Add a debug implementation for Address

* fmt

* Ensure debug works for messagechannel & show RC info

* format

* Add test

* Remove refcounter type from struct name

* Ensure debug works for messagechannel & show RC info

* Fix rebase issue

* Turbofish over type annotation (@thomaseizinger)

Thanks to @thomaseizinger!

Co-authored-by: Thomas Eizinger <[email protected]>

* Remove unnecessary locking

* rustfmt

* Try fix MSRV issue

* Revert (original change red herring)

Technically this is not an MSRV issue, this is an actions + not commiting Cargo.lock issue, since having async_global_executor on 2021 should be fine as long as your compiler is also on 2021, and xtra won't specifically bring in the 2021 edition as it.

Co-authored-by: Thomas Eizinger <[email protected]>
  • Loading branch information
Restioson and thomaseizinger committed Jun 10, 2022
1 parent e1a6f57 commit c3ef497
Show file tree
Hide file tree
Showing 4 changed files with 67 additions and 9 deletions.
10 changes: 9 additions & 1 deletion src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@ use flume::r#async::SendSink;
use futures_core::Stream;
use futures_sink::Sink;
use futures_util::{future, StreamExt};
use std::fmt::{self, Display, Formatter};
use std::fmt::{self, Debug, Display, Formatter};
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll};
Expand Down Expand Up @@ -45,6 +45,14 @@ pub struct Address<A: 'static, Rc: RefCounter = Strong> {
pub(crate) ref_counter: Rc,
}

impl<A, Rc: RefCounter> Debug for Address<A, Rc> {
fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
f.debug_struct(&format!("Address<{}>", std::any::type_name::<A>()))
.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)
Expand Down
5 changes: 3 additions & 2 deletions src/message_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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;

Expand Down Expand Up @@ -76,10 +78,9 @@ use crate::{Handler, KeepRunning};
/// })
/// }
/// ```
pub trait MessageChannel<M>: Sealed + Unpin + Send {
pub trait MessageChannel<M>: Sealed + Unpin + Debug + Send {
/// 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;

Expand Down
39 changes: 33 additions & 6 deletions src/refcount.rs
Original file line number Diff line number Diff line change
@@ -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.
Expand All @@ -18,6 +17,16 @@ pub struct Strong {
lock: Arc<RwLock<()>>,
}

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,
Expand All @@ -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),
Expand All @@ -55,17 +68,31 @@ pub struct Weak {
lock: Arc<RwLock<()>>,
}

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<Strong> {
ArcWeak::upgrade(&self.shared).map(|shared| Strong {
shared,
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),
Expand All @@ -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)]
Expand Down
22 changes: 22 additions & 0 deletions tests/basic.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::<Greeter>::new(None);

let addr2 = addr1.clone();
let weak_addr = addr2.downgrade();

assert_eq!(
format!("{:?}", addr1),
"Address<basic::Greeter> { \
ref_counter: Strong { connected: true, strong_count: 2, weak_count: 2 } }"
);

assert_eq!(format!("{:?}", addr1), format!("{:?}", addr2));

assert_eq!(
format!("{:?}", weak_addr),
"Address<basic::Greeter> { \
ref_counter: Weak { connected: true, strong_count: 2, weak_count: 2 } }"
);
}

0 comments on commit c3ef497

Please sign in to comment.