behavior_actors/
shutdown.rs1use crate::protocol::ShutdownRequested;
9use behavior::Step;
10use behavior::{
11 Actions, Address, Behavior, BirthMode, EventLayer, NoSends, SendEffects, SendLayer,
12};
13
14pub type ShutdownEvent<E> = EventLayer<ShutdownRequested, E>;
16
17pub struct StopOnShutdown<B> {
19 inner: B,
20}
21
22impl<B> StopOnShutdown<B> {
23 #[must_use]
29 pub const fn new(inner: B) -> Self {
30 Self { inner }
31 }
32
33 #[must_use]
35 pub fn into_inner(self) -> B {
36 self.inner
37 }
38}
39
40impl<B: Behavior + behavior::BehaviorBase> behavior::BehaviorBase for StopOnShutdown<B> {
41 type Base = B::Base;
42
43 fn base(&self) -> &Self::Base {
44 self.inner.base()
45 }
46}
47
48impl<B: crate::StashStatus> crate::StashStatus for StopOnShutdown<B> {
49 fn stashed_messages(&self) -> usize {
50 self.inner.stashed_messages()
51 }
52}
53
54pub type ShutdownReaction<B> = fn(
57 &mut B,
58 ShutdownRequested,
59) -> Actions<
60 behavior::BehaviorAddr<B>,
61 <B as Behavior>::Ph,
62 <B as Behavior>::Sends,
63 <B as Behavior>::Birth,
64>;
65
66pub struct FinalizeOnShutdown<B: Behavior> {
87 inner: B,
88 finalize: ShutdownReaction<B>,
89}
90
91impl<B: Behavior> FinalizeOnShutdown<B> {
92 #[must_use]
99 pub const fn new(inner: B, finalize: ShutdownReaction<B>) -> Self {
100 Self { inner, finalize }
101 }
102}
103
104impl<B: Behavior + behavior::BehaviorBase> behavior::BehaviorBase for FinalizeOnShutdown<B> {
105 type Base = B::Base;
106
107 fn base(&self) -> &Self::Base {
108 self.inner.base()
109 }
110}
111
112impl<B> crate::StashStatus for FinalizeOnShutdown<B>
113where
114 B: Behavior + crate::StashStatus,
115{
116 fn stashed_messages(&self) -> usize {
117 self.inner.stashed_messages()
118 }
119}
120
121macro_rules! impl_shutdown_behavior {
122 ($wrapper:ident, $shutdown:expr) => {
123 impl<B, A, Ph, Sends, Br> Behavior for $wrapper<B>
124 where
125 A: Address,
126 Sends: SendEffects + behavior::SendsFor<B::Event>,
127 Br: BirthMode,
128 B: Behavior<Ph = Ph, Sends = Sends, Birth = Br>,
129 B::Protocol: behavior::Protocol<Addr = A>,
130 {
131 type Protocol = B::Protocol;
132 type Event = ShutdownEvent<B::Event>;
133 type Sends = SendLayer<NoSends, Sends>;
134 type Ph = Ph;
135 type Error = B::Error;
136 type Birth = Br;
137
138 fn init(
139 &mut self,
140 _: behavior::InitializationTurn,
141 ) -> Result<Actions<A, Ph, Self::Sends, Br>, B::Error> {
142 behavior::initialize(&mut self.inner)
143 .map(|actions| actions.map_sends(|inner| SendLayer::new(NoSends, inner)))
144 }
145
146 fn transition(
147 &mut self,
148 _: behavior::ActiveTurn,
149 event: Self::Event,
150 ) -> Result<Actions<A, Ph, Self::Sends, Br>, B::Error> {
151 match event {
152 EventLayer::Inner(event) => {
153 behavior::delegate_transition(&mut self.inner, event).map(|actions| {
154 actions.map_sends(|inner| SendLayer::new(NoSends, inner))
155 })
156 }
157 EventLayer::Owned(request) => $shutdown(self, request),
158 }
159 }
160 }
161 };
162}
163
164impl_shutdown_behavior!(StopOnShutdown, |_this: &mut StopOnShutdown<B>, _request| {
165 Ok(Actions::stop())
166});
167
168impl_shutdown_behavior!(
169 FinalizeOnShutdown,
170 |this: &mut FinalizeOnShutdown<B>, request| {
171 let actions = (this.finalize)(&mut this.inner, request);
172 Ok(actions
173 .map_become(|_| Step::Stop(behavior::Stopped))
174 .map_sends(|inner| SendLayer::new(NoSends, inner)))
175 }
176);