actix/
context.rs

1use std::fmt;
2
3use crate::{
4    actor::{Actor, ActorContext, ActorState, AsyncContext, SpawnHandle},
5    address::{Addr, AddressReceiver},
6    context_impl::{AsyncContextParts, ContextFut, ContextParts},
7    fut::ActorFuture,
8    mailbox::Mailbox,
9};
10
11/// An actor execution context.
12pub struct Context<A>
13where
14    A: Actor<Context = Context<A>>,
15{
16    parts: ContextParts<A>,
17    mb: Option<Mailbox<A>>,
18}
19
20impl<A: Actor<Context = Context<A>>> fmt::Debug for Context<A> {
21    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
22        fmt.debug_struct("Context")
23            .field("parts", &self.parts)
24            .field("mb", &self.mb)
25            .finish()
26    }
27}
28
29impl<A> ActorContext for Context<A>
30where
31    A: Actor<Context = Self>,
32{
33    #[inline]
34    fn stop(&mut self) {
35        self.parts.stop()
36    }
37    #[inline]
38    fn terminate(&mut self) {
39        self.parts.terminate()
40    }
41    #[inline]
42    fn state(&self) -> ActorState {
43        self.parts.state()
44    }
45}
46
47impl<A> AsyncContext<A> for Context<A>
48where
49    A: Actor<Context = Self>,
50{
51    #[inline]
52    fn spawn<F>(&mut self, fut: F) -> SpawnHandle
53    where
54        F: ActorFuture<A, Output = ()> + 'static,
55    {
56        self.parts.spawn(fut)
57    }
58
59    #[inline]
60    fn wait<F>(&mut self, fut: F)
61    where
62        F: ActorFuture<A, Output = ()> + 'static,
63    {
64        self.parts.wait(fut)
65    }
66
67    #[inline]
68    fn waiting(&self) -> bool {
69        self.parts.waiting()
70    }
71
72    #[inline]
73    fn cancel_future(&mut self, handle: SpawnHandle) -> bool {
74        self.parts.cancel_future(handle)
75    }
76
77    #[inline]
78    fn address(&self) -> Addr<A> {
79        self.parts.address()
80    }
81}
82
83impl<A> Context<A>
84where
85    A: Actor<Context = Self>,
86{
87    /// Create a context without spawning it.
88    ///
89    /// The context can be spawned into an actor using its [`run`](`Context::run`) method.
90    ///
91    /// ```
92    /// # use actix::prelude::*;
93    /// struct Actor1 {
94    ///     actor2_addr: Addr<Actor2>,
95    /// }
96    /// # impl Actor for Actor1 {
97    /// #     type Context = Context<Self>;
98    /// # }
99    ///
100    /// struct Actor2 {
101    ///     actor1_addr: Addr<Actor1>,
102    /// }
103    /// # impl Actor for Actor2 {
104    /// #     type Context = Context<Self>;
105    /// #
106    /// #     fn started(&mut self, _: &mut Self::Context) {
107    /// #         System::current().stop();
108    /// #     }        
109    /// # }
110    ///
111    /// # fn main() {
112    /// # let sys = System::new();
113    /// # sys.block_on(async {
114    /// let ctx1 = Context::<Actor1>::new();
115    /// let ctx2 = Context::<Actor2>::new();
116    ///
117    /// let actor1 = Actor1 { actor2_addr: ctx2.address() };
118    /// let actor2 = Actor2 { actor1_addr: ctx1.address() };
119    ///
120    /// ctx1.run(actor1);
121    /// ctx2.run(actor2);
122    /// # });
123    /// # sys.run().unwrap();
124    /// # }
125    /// ```
126    #[inline]
127    pub fn new() -> Self {
128        let mb = Mailbox::default();
129        Self {
130            parts: ContextParts::new(mb.sender_producer()),
131            mb: Some(mb),
132        }
133    }
134
135    #[inline]
136    pub fn with_receiver(rx: AddressReceiver<A>) -> Self {
137        let mb = Mailbox::new(rx);
138        Self {
139            parts: ContextParts::new(mb.sender_producer()),
140            mb: Some(mb),
141        }
142    }
143
144    #[inline]
145    pub fn run(self, act: A) -> Addr<A> {
146        let fut = self.into_future(act);
147        let addr = fut.address();
148        actix_rt::spawn(fut);
149        addr
150    }
151
152    pub fn into_future(mut self, act: A) -> ContextFut<A, Self> {
153        let mb = self.mb.take().unwrap();
154        ContextFut::new(self, act, mb)
155    }
156
157    /// Returns a handle to the running future.
158    ///
159    /// This is the handle returned by the `AsyncContext::spawn()`
160    /// method.
161    pub fn handle(&self) -> SpawnHandle {
162        self.parts.curr_handle()
163    }
164
165    /// Sets the mailbox capacity.
166    ///
167    /// The default mailbox capacity is 16 messages.
168    /// #Examples
169    /// ```
170    /// # use actix::prelude::*;
171    /// struct MyActor;
172    /// impl Actor for MyActor {
173    ///     type Context = Context<Self>;
174    ///
175    ///     fn started(&mut self, ctx: &mut Self::Context) {
176    ///         ctx.set_mailbox_capacity(1);
177    ///         System::current().stop();
178    ///     }
179    /// }
180    ///
181    /// # fn main() {
182    /// # let mut sys = System::new();
183    /// let addr = sys.block_on(async { MyActor.start() });
184    /// sys.run();
185    /// # }
186    /// ```
187    pub fn set_mailbox_capacity(&mut self, cap: usize) {
188        self.parts.set_mailbox_capacity(cap)
189    }
190
191    /// Returns whether any addresses are still connected.
192    pub fn connected(&self) -> bool {
193        self.parts.connected()
194    }
195}
196
197impl<A> Default for Context<A>
198where
199    A: Actor<Context = Self>,
200{
201    #[inline]
202    fn default() -> Self {
203        Self::new()
204    }
205}
206
207impl<A> AsyncContextParts<A> for Context<A>
208where
209    A: Actor<Context = Self>,
210{
211    fn parts(&mut self) -> &mut ContextParts<A> {
212        &mut self.parts
213    }
214}
215
216/// Helper trait which can spawn a future into the actor's context.
217pub trait ContextFutureSpawner<A>
218where
219    A: Actor,
220    A::Context: AsyncContext<A>,
221{
222    /// Spawns the future into the given context.
223    fn spawn(self, ctx: &mut A::Context);
224
225    /// Spawns the future into the given context, waiting for it to
226    /// resolve.
227    ///
228    /// This stops processing any incoming events until this future
229    /// resolves.
230    fn wait(self, ctx: &mut A::Context);
231}
232
233impl<A, T> ContextFutureSpawner<A> for T
234where
235    A: Actor,
236    A::Context: AsyncContext<A>,
237    T: ActorFuture<A, Output = ()> + 'static,
238{
239    #[inline]
240    fn spawn(self, ctx: &mut A::Context) {
241        let _ = ctx.spawn(self);
242    }
243
244    #[inline]
245    fn wait(self, ctx: &mut A::Context) {
246        ctx.wait(self);
247    }
248}