tiny_actor/actor/
spawning.rs

1use crate::*;
2use futures::Future;
3use std::sync::Arc;
4
5/// Spawn a new actor with a single process, this returns a [Child] and an [Address].
6///
7/// # Example
8/// ```no_run
9///# use tiny_actor::*;
10///# #[tokio::main]
11///# async fn main() {
12/// let (child, address) =
13///     spawn(Config::default(), |mut inbox: Inbox<u32>| async move {
14///         loop {
15///             let msg = inbox.recv().await;
16///             println!("Received message: {msg:?}");
17///         }
18///     });
19///# }
20/// ```
21pub fn spawn<M, E, Fun, Fut>(
22    config: Config,
23    fun: Fun,
24) -> (Child<E, Channel<M>>, Address<Channel<M>>)
25where
26    Fun: FnOnce(Inbox<M>) -> Fut + Send + 'static,
27    Fut: Future<Output = E> + Send + 'static,
28    E: Send + 'static,
29    M: Send + 'static,
30{
31    let channel = Arc::new(Channel::<M>::new(1, 1, config.capacity));
32    let address = Address::from_channel(channel.clone());
33    let inbox = Inbox::from_channel(channel.clone());
34
35    let handle = tokio::task::spawn(async move { fun(inbox).await });
36
37    let child = Child::new(channel, handle, config.link);
38
39    (child, address)
40}
41
42/// Spawn a new actor with a single process, this returns a [Child] and an [Address].
43///
44/// This is the same as [spawn], but returns a [ChildPool] instead of a [Child].
45///
46/// # Example
47/// ```no_run
48///# use tiny_actor::*;
49///# #[tokio::main]
50///# async fn main() {
51/// let (child_pool, address) =
52///     spawn_one(Config::default(), |mut inbox: Inbox<u32>| async move {
53///         loop {
54///             let msg = inbox.recv().await;
55///             println!("Received message: {msg:?}");
56///         }
57///     });
58///# }
59/// ```
60pub fn spawn_one<M, E, Fun, Fut>(
61    config: Config,
62    fun: Fun,
63) -> (ChildPool<E, Channel<M>>, Address<Channel<M>>)
64where
65    Fun: FnOnce(Inbox<M>) -> Fut + Send + 'static,
66    Fut: Future<Output = E> + Send + 'static,
67    E: Send + 'static,
68    M: Send + 'static,
69{
70    let channel = Arc::new(Channel::<M>::new(1, 1, config.capacity));
71    let address = Address::from_channel(channel.clone());
72    let inbox = Inbox::from_channel(channel.clone());
73
74    let handle = tokio::task::spawn(async move { fun(inbox).await });
75
76    let child = ChildPool::new(channel, vec![handle], config.link);
77
78    (child, address)
79}
80
81/// Spawn a new actor with a multiple process, this returns a [ChildPool] and an [Address].
82///
83/// The iterator will be passed along as the first argument to every spawned function.
84///
85/// # Example
86/// ```no_run
87///# use tiny_actor::*;
88///# #[tokio::main]
89///# async fn main() {
90/// let (child_pool, address) =
91///     spawn_many(0..5, Config::default(), |i, mut inbox: Inbox<u32>| async move {
92///         loop {
93///             let msg = inbox.recv().await;
94///             println!("Received message on actor {i}: {msg:?}");
95///         }
96///     });
97///# }
98/// ```
99pub fn spawn_many<M, E, I, Fun, Fut>(
100    iter: impl IntoIterator<Item = I>,
101    config: Config,
102    fun: Fun,
103) -> (ChildPool<E, Channel<M>>, Address<Channel<M>>)
104where
105    Fun: FnOnce(I, Inbox<M>) -> Fut + Send + 'static + Clone,
106    Fut: Future<Output = E> + Send + 'static,
107    E: Send + 'static,
108    M: Send + 'static,
109    I: Send + 'static,
110{
111    let iter = iter.into_iter();
112    let channel = Arc::new(Channel::<M>::new(1, 1, config.capacity));
113    let address = Address::from_channel(channel.clone());
114
115    let handles = iter
116        .map(|i| {
117            let fun = fun.clone();
118            let inbox = Inbox::from_channel(address.channel().clone());
119            tokio::task::spawn(async move { fun(i, inbox).await })
120        })
121        .collect::<Vec<_>>();
122
123    address.channel().set_inbox_count(handles.len());
124
125    let child = ChildPool::new(channel, handles, config.link);
126
127    (child, address)
128}