Skip to content

Commit

Permalink
Remove stopping (#82)
Browse files Browse the repository at this point in the history
* Remove stopping and repurpose KeepRunning

* Fix build - logic will be fixed in #83

* Change stop_all behaviour - in line with stop_self

Previously, stop_all would immediately disconnect the address. However, stop_self done on every actor would actually not do this in one case - if there were a free-floating (not executing an actor event loop) Context. This change brings stop_all in line with stop_self.

* Fmt + document more breaking changes

* merge oversight
  • Loading branch information
Restioson authored Jun 17, 2022
1 parent ab753bc commit 434788e
Show file tree
Hide file tree
Showing 8 changed files with 173 additions and 244 deletions.
12 changes: 7 additions & 5 deletions BREAKING-CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,17 +1,19 @@
# Breaking Changes by Version

## Unreleased

- `Context::notify_interval` and `Context::notify_after` are now subject to back-pressure.
These aren't API breaking but a semantic changes.

## 0.6.0

- Sealed `RefCounter`, `MessageChannel`, and `MessageSink` traits
- `AddressSink` no longer exists - `Address` now implements `Sink` directly for any handlers returning `()`.
- `Message` no longer exists - `Return` is now specified on the `Handler` trait itself.
- `Address` is no longer `Sync`, due to it implementing `AddressSink`. You should just be able to clone it and then send
it, though.
- `Context::notify_interval` and `Context::notify_after` are now subject to back-pressure, in case the address mailbox
is full. These aren't API breaking but a semantic changes.
- `stopping` has been removed in favour of `stop_self` and `stop_all`. If logic to determine if the actor should stop
must be executed, it should be done rather at the point of calling `stop_{self,all}`.
- Previously, `stop_all` would immediately disconnect the address. However, `stop_self` done on every actor would actually
not do this in one case - if there were a free-floating (not executing an actor event loop) Context. This change brings
`stop_all` in line with `stop_self`.

## 0.5.0

Expand Down
7 changes: 6 additions & 1 deletion examples/message_stealing.rs
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ impl Handler<Print> for Printer {

if self.times == 10 {
println!("Actor {} stopping!", self.id);
ctx.stop();
ctx.stop_all();
}
}
}
Expand All @@ -55,6 +55,11 @@ async fn main() {
smol::spawn(ctx.attach(Printer::new(n))).detach();
}

// This must be dropped, otherwise it will keep the actors from correctly shutting down. It
// doesn't affect this example, but it's best practice if not planning to use this behaviour
// intentionally.
drop(ctx);

while addr.send(Print("hello".to_string())).await.is_ok() {}
println!("Stopping to send");

Expand Down
11 changes: 7 additions & 4 deletions src/address.rs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ pub struct Address<A: 'static, Rc: RefCounter = Strong> {
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("connected", &self.is_connected())
.field("ref_counter", &self.ref_counter)
.finish()
}
Expand Down Expand Up @@ -87,7 +88,7 @@ impl<A> Address<A, Either> {

/// Functions which apply to any kind of address, be they strong or weak.
impl<A, Rc: RefCounter> Address<A, Rc> {
/// Returns whether the actor referred to by this address is running and accepting messages.
/// Returns whether the actors referred to by this address are running and accepting messages.
///
/// ```rust
/// # use xtra::prelude::*;
Expand All @@ -101,7 +102,7 @@ impl<A, Rc: RefCounter> Address<A, Rc> {
/// type Return = ();
///
/// async fn handle(&mut self, _: Shutdown, ctx: &mut Context<Self>) {
/// ctx.stop();
/// ctx.stop_all();
/// }
/// }
///
Expand All @@ -115,7 +116,7 @@ impl<A, Rc: RefCounter> Address<A, Rc> {
/// })
/// ```
pub fn is_connected(&self) -> bool {
!self.sink.is_disconnected()
!self.sink.is_disconnected() && self.ref_counter.is_connected()
}

/// Returns the number of messages in the actor's mailbox.
Expand Down Expand Up @@ -208,7 +209,9 @@ impl<A, Rc: RefCounter> Address<A, Rc> {
}
}

/// Waits until this address becomes disconnected.
/// Waits until this address becomes disconnected. Note that if this is called on a strong
/// address, it will only ever trigger if the actor calls [`Context::stop`], as the address
/// would prevent the actor being dropped due to too few strong addresses.
pub fn join(&self) -> ActorJoinHandle {
ActorJoinHandle(self.ref_counter.disconnect_notice())
}
Expand Down
Loading

0 comments on commit 434788e

Please sign in to comment.