actix/fut/future/mod.rs
1use std::{
2 future::Future,
3 marker::PhantomData,
4 ops::{Deref, DerefMut},
5 pin::Pin,
6 task::{Context, Poll},
7 time::Duration,
8};
9
10pub use map::Map;
11use pin_project_lite::pin_project;
12pub use then::Then;
13pub use timeout::Timeout;
14
15use crate::actor::Actor;
16
17mod either;
18mod map;
19pub mod result;
20mod then;
21mod timeout;
22
23/// Trait for types which are a placeholder of a value that may become
24/// available at some later point in time.
25///
26/// [`ActorFuture`] is very similar to a regular [`Future`], only with subsequent combinator
27/// closures accepting the actor and its context, in addition to the result.
28///
29/// [`ActorFuture`] allows for use cases where future processing requires access to the actor or
30/// its context.
31///
32/// Here is an example of a handler on a single actor, deferring work to another actor, and then
33/// updating the initiating actor's state:
34///
35/// ```no_run
36/// use actix::prelude::*;
37///
38/// // The response type returned by the actor future
39/// type OriginalActorResponse = ();
40/// // The error type returned by the actor future
41/// type MessageError = ();
42/// // This is the needed result for the DeferredWork message
43/// // It's a result that combine both Response and Error from the future response.
44/// type DeferredWorkResult = Result<OriginalActorResponse, MessageError>;
45/// #
46/// # struct ActorState {}
47/// #
48/// # impl ActorState {
49/// # fn update_from(&mut self, _result: ()) {}
50/// # }
51/// #
52/// # struct OtherActor {}
53/// #
54/// # impl Actor for OtherActor {
55/// # type Context = Context<Self>;
56/// # }
57/// #
58/// # impl Handler<OtherMessage> for OtherActor {
59/// # type Result = ();
60/// #
61/// # fn handle(&mut self, _msg: OtherMessage, _ctx: &mut Context<Self>) -> Self::Result {}
62/// # }
63/// #
64/// # struct OriginalActor{
65/// # other_actor: Addr<OtherActor>,
66/// # inner_state: ActorState
67/// # }
68/// #
69/// # impl Actor for OriginalActor{
70/// # type Context = Context<Self>;
71/// # }
72/// #
73/// # #[derive(Message)]
74/// # #[rtype(result = "Result<(), MessageError>")]
75/// # struct DeferredWork {}
76/// #
77/// # #[derive(Message)]
78/// # #[rtype(result = "()")]
79/// # struct OtherMessage {}
80///
81/// impl Handler<DeferredWork> for OriginalActor {
82/// // Notice the `Response` is an `ActorFuture`-ized version of `Self::Message::Result`.
83/// type Result = ResponseActFuture<Self, DeferredWorkResult>;
84///
85/// fn handle(&mut self, _msg: DeferredWork, _ctx: &mut Context<Self>) -> Self::Result {
86/// // this creates a `Future` representing the `.send` and subsequent
87/// // `Result` from `other_actor`
88/// let update_self = self.other_actor
89/// .send(OtherMessage {})
90/// // Wrap that future so chained handlers can access the actor
91/// // (`self` in the synchronous code) as well as the context.
92/// .into_actor(self)
93/// // once the wrapped future resolves, update this actor's state
94/// .map(|result, actor, _ctx| {
95/// match result {
96/// Ok(v) => {
97/// // update actor (self) state
98/// actor.inner_state.update_from(v);
99/// Ok(())
100/// },
101/// // Failed to send message to other_actor
102/// Err(_e) => Err(()),
103/// }
104/// });
105///
106/// // box and return the wrapped future
107/// Box::pin(update_self)
108/// }
109/// }
110/// ```
111///
112/// See also [`WrapFuture::into_actor()`] which provides future conversion.
113pub trait ActorFuture<A: Actor> {
114 /// The type of value produced on completion.
115 type Output;
116
117 fn poll(
118 self: Pin<&mut Self>,
119 srv: &mut A,
120 ctx: &mut A::Context,
121 task: &mut Context<'_>,
122 ) -> Poll<Self::Output>;
123}
124
125pub trait ActorFutureExt<A: Actor>: ActorFuture<A> {
126 /// Map this future's result to a different type, returning a new future of
127 /// the resulting type.
128 fn map<F, U>(self, f: F) -> Map<Self, F>
129 where
130 F: FnOnce(Self::Output, &mut A, &mut A::Context) -> U,
131 Self: Sized,
132 {
133 Map::new(self, f)
134 }
135
136 /// Chain on a computation for when a future finished, passing the result of
137 /// the future to the provided closure `f`.
138 fn then<F, Fut>(self, f: F) -> Then<Self, Fut, F>
139 where
140 F: FnOnce(Self::Output, &mut A, &mut A::Context) -> Fut,
141 Fut: ActorFuture<A>,
142 Self: Sized,
143 {
144 then::new(self, f)
145 }
146
147 /// Add timeout to futures chain.
148 ///
149 /// `Err(())` returned as a timeout error.
150 fn timeout(self, timeout: Duration) -> Timeout<Self>
151 where
152 Self: Sized,
153 {
154 Timeout::new(self, timeout)
155 }
156
157 /// Wrap the future in a Box, pinning it.
158 ///
159 /// A shortcut for wrapping in [`Box::pin`].
160 fn boxed_local(self) -> LocalBoxActorFuture<A, Self::Output>
161 where
162 Self: Sized + 'static,
163 {
164 Box::pin(self)
165 }
166}
167
168impl<F, A> ActorFutureExt<A> for F
169where
170 F: ActorFuture<A>,
171 A: Actor,
172{
173}
174
175/// Type alias for a pinned box [`ActorFuture`] trait object.
176pub type LocalBoxActorFuture<A, I> = Pin<Box<dyn ActorFuture<A, Output = I>>>;
177
178impl<F, A> ActorFuture<A> for Box<F>
179where
180 F: ActorFuture<A> + Unpin + ?Sized,
181 A: Actor,
182{
183 type Output = F::Output;
184
185 fn poll(
186 mut self: Pin<&mut Self>,
187 srv: &mut A,
188 ctx: &mut A::Context,
189 task: &mut Context<'_>,
190 ) -> Poll<Self::Output> {
191 Pin::new(&mut **self.as_mut()).poll(srv, ctx, task)
192 }
193}
194
195impl<P, A> ActorFuture<A> for Pin<P>
196where
197 P: Unpin + DerefMut,
198 <P as Deref>::Target: ActorFuture<A>,
199 A: Actor,
200{
201 type Output = <<P as Deref>::Target as ActorFuture<A>>::Output;
202
203 fn poll(
204 self: Pin<&mut Self>,
205 srv: &mut A,
206 ctx: &mut A::Context,
207 task: &mut Context<'_>,
208 ) -> Poll<Self::Output> {
209 Pin::get_mut(self).as_mut().poll(srv, ctx, task)
210 }
211}
212
213/// Helper trait that allows conversion of normal future into [`ActorFuture`]
214pub trait WrapFuture<A>
215where
216 A: Actor,
217{
218 /// The future that this type can be converted into.
219 type Future: ActorFuture<A>;
220
221 #[deprecated(since = "0.11.0", note = "Please use WrapFuture::into_actor")]
222 #[doc(hidden)]
223 fn actfuture(self) -> Self::Future;
224
225 /// Convert normal future to a [`ActorFuture`]
226 fn into_actor(self, a: &A) -> Self::Future;
227}
228
229impl<F: Future, A: Actor> WrapFuture<A> for F {
230 type Future = FutureWrap<F, A>;
231
232 #[doc(hidden)]
233 fn actfuture(self) -> Self::Future {
234 wrap_future(self)
235 }
236
237 fn into_actor(self, _: &A) -> Self::Future {
238 wrap_future(self)
239 }
240}
241
242pin_project! {
243 pub struct FutureWrap<F, A>
244 where
245 F: Future,
246 A: Actor,
247 {
248 #[pin]
249 fut: F,
250 _act: PhantomData<A>
251 }
252}
253
254/// Converts normal future into [`ActorFuture`], allowing its processing to
255/// use the actor's state.
256///
257/// See the documentation for [`ActorFuture`] for a practical example involving both
258/// [`wrap_future`] and [`ActorFuture`]
259pub fn wrap_future<F, A>(f: F) -> FutureWrap<F, A>
260where
261 F: Future,
262 A: Actor,
263{
264 FutureWrap {
265 fut: f,
266 _act: PhantomData,
267 }
268}
269
270impl<F, A> ActorFuture<A> for FutureWrap<F, A>
271where
272 F: Future,
273 A: Actor,
274{
275 type Output = F::Output;
276
277 fn poll(
278 self: Pin<&mut Self>,
279 _: &mut A,
280 _: &mut A::Context,
281 task: &mut Context<'_>,
282 ) -> Poll<Self::Output> {
283 self.project().fut.poll(task)
284 }
285}