1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
use crate::{ActoId, PanicOrAbort};
use std::mem::discriminant;
/// Actor input as received with [`ActoCell::recv`].
#[derive(Debug)]
pub enum ActoInput<M, S> {
/// All previously generated [`ActoRef`] handles were dropped, leaving only
/// the one within [`ActoCell`]; the actor may wish to terminate unless it has
/// other sources of input.
///
/// Obtaining a new handle with [`ActoCell::me`] and dropping it will again
/// generate this input.
NoMoreSenders,
/// A supervised actor with the given [`ActoId`] has terminated.
///
/// The result contains either the value returned by the actor or the value
/// with which the actor’s task panicked (if the underlying runtime handles this).
///
/// ## Important notice
///
/// Supervision notifications are delivered as soon as possible after the
/// supervised actor’s task has finished. Messages sent by that actor — possibly
/// to the supervisor — may still be in flight at this point.
Supervision {
id: ActoId,
name: String,
result: Result<S, PanicOrAbort>,
},
/// A message has been received via our [`ActoRef`] handle.
Message(M),
}
impl<M, S> ActoInput<M, S> {
pub fn is_sender_gone(&self) -> bool {
matches!(self, ActoInput::NoMoreSenders)
}
pub fn is_supervision(&self) -> bool {
matches!(self, ActoInput::Supervision { .. })
}
pub fn is_message(&self) -> bool {
matches!(self, ActoInput::Message(_))
}
/// Obtain input message or supervision unless this is [`ActoInput::NoMoreSenders`].
///
/// ```rust
/// use acto::{ActoCell, ActoRuntime};
///
/// async fn actor(mut cell: ActoCell<String, impl ActoRuntime>) {
/// while let Some(input) = cell.recv().await.has_senders() {
/// // do something with it
/// }
/// // actor automatically stops when all senders are gone
/// }
/// ```
pub fn has_senders(self) -> Option<ActoMsgSuper<M, S>> {
match self {
ActoInput::NoMoreSenders => None,
ActoInput::Supervision { id, name, result } => {
Some(ActoMsgSuper::Supervision { id, name, result })
}
ActoInput::Message(msg) => Some(ActoMsgSuper::Message(msg)),
}
}
}
impl<M: PartialEq, S> PartialEq for ActoInput<M, S> {
fn eq(&self, other: &Self) -> bool {
match (self, other) {
(Self::Supervision { id: left, .. }, Self::Supervision { id: right, .. }) => {
left == right
}
(Self::Message(l0), Self::Message(r0)) => l0 == r0,
_ => discriminant(self) == discriminant(other),
}
}
}
/// A filtered variant of [`ActoInput`] that omits `NoMoreSenders`.
///
/// see [`ActoInput::has_senders`]
pub enum ActoMsgSuper<M, S> {
Supervision {
id: ActoId,
name: String,
result: Result<S, PanicOrAbort>,
},
/// A message has been received via our [`ActoRef`] handle.
Message(M),
}