Skip to content

Commit

Permalink
feat: implement Hash for MessageChannel
Browse files Browse the repository at this point in the history
  • Loading branch information
jcdickinson committed Jul 3, 2024
1 parent f9c4704 commit 422b475
Showing 1 changed file with 74 additions and 0 deletions.
74 changes: 74 additions & 0 deletions xtra/src/message_channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
//! the message type rather than the actor type.
use std::fmt;
use std::hash::{Hash, Hasher};

use crate::address::{ActorJoinHandle, Address};
use crate::chan::RefCounter;
Expand Down Expand Up @@ -207,6 +208,17 @@ where
}
}

impl<M, R, Rc: RefCounter> Hash for MessageChannel<M, R, Rc>
where
M: Send + 'static,
R: Send + 'static,
Rc: Send + 'static,
{
fn hash<H: Hasher>(&self, state: &mut H) {
self.inner.hash(state)
}
}

impl<M, R, Rc> Clone for MessageChannel<M, R, Rc>
where
R: Send + 'static,
Expand Down Expand Up @@ -295,6 +307,8 @@ trait MessageChannelTrait<M, Rc> {
fn to_either(
&self,
) -> Box<dyn MessageChannelTrait<M, Either, Return = Self::Return> + Send + Sync + 'static>;

fn hash(&self, state: &mut dyn Hasher);
}

impl<A, R, M, Rc: RefCounter> MessageChannelTrait<M, Rc> for Address<A, Rc>
Expand Down Expand Up @@ -366,4 +380,64 @@ where
{
Box::new(Address(self.0.to_tx_either()))
}

fn hash(&self, state: &mut dyn Hasher) {
state.write_usize(self.0.inner_ptr() as *const _ as usize);
state.write_u8(self.0.is_strong() as u8);
state.finish();
}
}

#[cfg(test)]
mod test {
use std::collections::HashSet;

use crate::{Actor, Handler, Mailbox};

type TestMessageChannel = super::MessageChannel<TestMessage, ()>;

#[derive(Hash, PartialEq)]
struct ChannelKey(TestMessageChannel);
impl Eq for ChannelKey {}

struct TestActor;
struct TestMessage;

impl Actor for TestActor {
type Stop = ();

async fn stopped(self) -> Self::Stop {}
}

impl Handler<TestMessage> for TestActor {
type Return = ();

async fn handle(&mut self, _: TestMessage, _: &mut crate::Context<Self>) -> Self::Return {}
}

#[test]
fn hashcode_and_partial_eq() {
let mut hs = HashSet::new();
let (a1, _) = Mailbox::<TestActor>::unbounded();
let (a2, _) = Mailbox::<TestActor>::unbounded();
let c1 = TestMessageChannel::new(a1.clone());

hs.insert(ChannelKey(c1.clone()));
hs.insert(ChannelKey(c1.clone()));
assert_eq!(1, hs.len(), "a duplicate channel should not be inserted");

hs.insert(ChannelKey(TestMessageChannel::new(a1.clone())));
assert_eq!(
1,
hs.len(),
"a new channel from the same actor should not be inserted"
);

hs.insert(ChannelKey(TestMessageChannel::new(a2)));
assert_eq!(
2,
hs.len(),
"a channel for a different actor should be inserted"
);
}
}

0 comments on commit 422b475

Please sign in to comment.