Skip to content

Commit

Permalink
feat: add blocking_link and blocking_unlink methods to ActorRef
Browse files Browse the repository at this point in the history
  • Loading branch information
tqwewe committed Jan 13, 2025
1 parent 1ca8004 commit 888bcc0
Showing 1 changed file with 85 additions and 8 deletions.
93 changes: 85 additions & 8 deletions src/actor/actor_ref.rs
Original file line number Diff line number Diff line change
Expand Up @@ -366,10 +366,7 @@ where
/// # });
/// ```
#[inline]
pub async fn link<B>(&self, sibbling_ref: &ActorRef<B>)
where
B: Actor,
{
pub async fn link<B: Actor>(&self, sibbling_ref: &ActorRef<B>) {
if self.id == sibbling_ref.id() {
return;
}
Expand All @@ -380,6 +377,44 @@ where
sibbling_links.insert(self.id, self.weak_signal_mailbox());
}

/// Blockingly links two actors as siblings, ensuring they notify each other if either one dies.
///
/// This method is intended for use cases where you need to link actors in synchronous code.
/// For async contexts, [`link`] is preferred.
///
/// # Example
///
/// ```
/// # #[derive(kameo::Actor)]
/// # struct MyActor;
/// #
/// # struct Msg;
/// #
/// # impl kameo::message::Message<Msg> for MyActor {
/// # type Reply = ();
/// # async fn handle(&mut self, msg: Msg, ctx: kameo::message::Context<'_, Self, Self::Reply>) -> Self::Reply { }
/// # }
/// #
/// # tokio_test::block_on(async {
/// let actor_ref = kameo::spawn(MyActor);
/// let sibbling_ref = kameo::spawn(MyActor);
///
/// actor_ref.blocking_link(&sibbling_ref);
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// # });
/// ```
#[inline]
pub fn blocking_link<B: Actor>(&self, sibbling_ref: &ActorRef<B>) {
if self.id == sibbling_ref.id() {
return;
}

let mut this_links = self.links.blocking_lock();
let mut sibbling_links = sibbling_ref.links.blocking_lock();
this_links.insert(sibbling_ref.id(), sibbling_ref.weak_signal_mailbox());
sibbling_links.insert(self.id, self.weak_signal_mailbox());
}

/// Unlinks two previously linked sibling actors.
///
/// # Example
Expand All @@ -405,17 +440,59 @@ where
/// # });
/// ```
#[inline]
pub async fn unlink<B>(&self, sibbling: &ActorRef<B>)
pub async fn unlink<B>(&self, sibbling_ref: &ActorRef<B>)
where
B: Actor,
{
if self.id == sibbling.id() {
if self.id == sibbling_ref.id() {
return;
}

let (mut this_links, mut sibbling_links) =
tokio::join!(self.links.lock(), sibbling.links.lock());
this_links.remove(&sibbling.id());
tokio::join!(self.links.lock(), sibbling_ref.links.lock());
this_links.remove(&sibbling_ref.id());
sibbling_links.remove(&self.id);
}

/// Blockingly unlinks two previously linked sibling actors.
///
/// This method is intended for use cases where you need to link actors in synchronous code.
/// For async contexts, [`link`] is preferred.
///
/// # Example
///
/// ```
/// # #[derive(kameo::Actor)]
/// # struct MyActor;
/// #
/// # struct Msg;
/// #
/// # impl kameo::message::Message<Msg> for MyActor {
/// # type Reply = ();
/// # async fn handle(&mut self, msg: Msg, ctx: kameo::message::Context<'_, Self, Self::Reply>) -> Self::Reply { }
/// # }
/// #
/// # tokio_test::block_on(async {
/// let actor_ref = kameo::spawn(MyActor);
/// let sibbling_ref = kameo::spawn(MyActor);
///
/// actor_ref.blocking_link(&sibbling_ref);
/// actor_ref.blocking_unlink(&sibbling_ref);
/// # Ok::<(), Box<dyn std::error::Error>>(())
/// # });
/// ```
#[inline]
pub fn blocking_unlink<B>(&self, sibbling_ref: &ActorRef<B>)
where
B: Actor,
{
if self.id == sibbling_ref.id() {
return;
}

let mut this_links = self.links.blocking_lock();
let mut sibbling_links = sibbling_ref.links.blocking_lock();
this_links.remove(&sibbling_ref.id());
sibbling_links.remove(&self.id);
}

Expand Down

0 comments on commit 888bcc0

Please sign in to comment.