Link

Struct Link 

Source
pub struct Link<A: ActorLike> { /* private fields */ }

Implementations§

Source§

impl<A: ActorLike> Link<A>

Source

pub fn new( tx: <A::Channel as ActorChannel>::Sender, token: CancelToken<A::Cancel>, state: A::State, ) -> Self

Source

pub fn alive(&self) -> bool

Source

pub fn wait(&self) -> BoxFuture<'_, ()>

Source

pub fn state(&self) -> &A::State

Source§

impl<A: ActorLike> Link<A>

Source

pub async fn ask_dyn_async<T>( &self, message: T, ) -> BoxFuture<'static, <A as Handler<T>>::Reply>
where T: SyncTrait, A: Handler<T> + ActorLike<Message = Multi<A>>,

Source

pub async fn tell_dyn<T>(&self, message: T)
where T: SyncTrait, A: Handler<T> + ActorLike<Message = Multi<A>>,

Source

pub async fn relay_dyn<T>( &self, envelope: Envelope<T, <A as Handler<T>>::Reply>, )
where T: SyncTrait, A: Handler<T> + ActorLike<Message = Multi<A>>,

Source

pub async fn ask_dyn<T>(&self, message: T) -> <A as Handler<T>>::Reply
where T: SyncTrait, A: Handler<T> + ActorLike<Message = Multi<A>>,

Examples found in repository?
examples/ping_pong.rs (line 59)
52    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: StartPing) -> Self::Reply {
53        self.pong_actor = Some(msg.0);
54        
55        // Start the ping-pong game
56        if let Some(ref pong) = self.pong_actor {
57            self.ping_count += 1;
58            println!("Ping #{}", self.ping_count);
59            let _ = pong.ask_dyn(Ping(self.ping_count)).await;
60        }
61        
62        Ok(())
63    }
64}
65
66impl Handler<Pong> for PingActor {
67    type Reply = Result<(), anyhow::Error>;
68
69    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: Pong) -> Self::Reply {
70        println!("Received Pong #{}", msg.0);
71        
72        // Continue ping-pong for a few rounds
73        if self.ping_count < 5 {
74            if let Some(ref pong) = self.pong_actor {
75                self.ping_count += 1;
76                println!("Ping #{}", self.ping_count);
77                let _ = pong.ask_dyn(Ping(self.ping_count)).await;
78            }
79        } else {
80            println!("Ping-pong game finished!");
81        }
82        
83        Ok(())
84    }
85}
86
87// Pong Actor implementation
88impl Actor for PongActor {
89    type Spec = ();
90    type Message = Multi<Self>;
91    type Channel = MpscChannel<Self::Message>;
92    type Cancel = ();
93    type State = ();
94
95    fn state(_spec: &Self::Spec) -> Self::State {}
96
97    fn init(_ctx: Init<'_, Self>) -> impl Future<Output = Result<Self, Self::Cancel>> + Send + 'static {
98        async move {
99            println!("PongActor initialized");
100            Ok(PongActor { pong_count: 0 })
101        }
102    }
103}
104
105impl Handler<Ping> for PongActor {
106    type Reply = Result<(), anyhow::Error>;
107
108    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: Ping) -> Self::Reply {
109        self.pong_count += 1;
110        println!("Received Ping #{}, sending Pong #{}", msg.0, self.pong_count);
111        
112        // We need the ping actor reference to send back Pong
113        // For this example, we'll use the actor context to get the sender
114        Ok(())
115    }
116}
117
118// Since we need bidirectional communication, let's modify the approach
119#[derive(Debug)]
120pub struct PingPong {
121    other_actor: Option<Link<PingPong>>,
122    is_ping: bool,
123    count: u32,
124}
125
126#[derive(Debug)]
127pub struct Connect(pub Link<PingPong>);
128
129#[derive(Debug)]
130pub struct Ball(pub u32);
131
132impl Actor for PingPong {
133    type Spec = bool; // true for ping, false for pong
134    type Message = Multi<Self>;
135    type Channel = MpscChannel<Self::Message>;
136    type Cancel = ();
137    type State = ();
138
139    fn state(_spec: &Self::Spec) -> Self::State {}
140
141    fn init(ctx: Init<'_, Self>) -> impl Future<Output = Result<Self, Self::Cancel>> + Send + 'static {
142        let is_ping = ctx.spec;
143        async move {
144            let name = if is_ping { "Ping" } else { "Pong" };
145            println!("{} actor initialized", name);
146            Ok(PingPong {
147                other_actor: None,
148                is_ping,
149                count: 0,
150            })
151        }
152    }
153}
154
155impl Handler<Connect> for PingPong {
156    type Reply = Result<(), anyhow::Error>;
157
158    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: Connect) -> Self::Reply {
159        self.other_actor = Some(msg.0);
160        
161        // If this is the ping actor, start the game
162        if self.is_ping {
163            if let Some(ref other) = self.other_actor {
164                self.count = 1;
165                println!("Ping sends ball #{}", self.count);
166                let _ = other.ask_dyn(Ball(self.count)).await;
167            }
168        }
169        
170        Ok(())
171    }
172}
173
174impl Handler<Ball> for PingPong {
175    type Reply = Result<(), anyhow::Error>;
176
177    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: Ball) -> Self::Reply {
178        let name = if self.is_ping { "Ping" } else { "Pong" };
179        println!("{} receives ball #{}", name, msg.0);
180        
181        if msg.0 < 10 {
182            if let Some(ref other) = self.other_actor {
183                let next_count = msg.0 + 1;
184                println!("{} sends ball #{}", name, next_count);
185                let _ = other.ask_dyn(Ball(next_count)).await;
186            }
187        } else {
188            println!("{} stops the game at ball #{}", name, msg.0);
189        }
190        
191        Ok(())
192    }
193}
194
195#[tokio::main]
196async fn main() -> anyhow::Result<()> {
197    // Spawn ping and pong actors
198    let ping = spawn::<PingPong>(true);
199    let pong = spawn::<PingPong>(false);
200
201    // Connect them
202    let _ = ping.ask_dyn(Connect(pong.clone())).await;
203    let _ = pong.ask_dyn(Connect(ping)).await;
204
205    // Wait for the game to finish
206    sleep(Duration::from_secs(2)).await;
207
208    Ok(())
209}
More examples
Hide additional examples
examples/bank_account.rs (line 130)
112    async fn handle(&mut self, _ctx: Call<'_, Self, Self::Reply>, msg: Transfer) -> Self::Reply {
113        if msg.amount <= 0.0 {
114            return Err(BankError::InvalidAmount { amount: msg.amount }.into());
115        }
116
117        if self.balance < msg.amount {
118            return Err(BankError::InsufficientFunds { 
119                balance: self.balance, 
120                requested: msg.amount 
121            }.into());
122        }
123
124        // Withdraw from this account
125        self.balance -= msg.amount;
126        println!("Account {}: Transfer out ${:.2}, new balance: ${:.2}", 
127                 self.account_number, msg.amount, self.balance);
128
129        // Deposit to target account
130        let _ = msg.to_account.ask_dyn(Deposit { amount: msg.amount }).await?;
131        println!("Transfer of ${:.2} completed from {} to target account", 
132                 msg.amount, self.account_number);
133
134        Ok(())
135    }
136}
137
138#[tokio::main]
139async fn main() -> anyhow::Result<()> {
140    // Create two bank accounts
141    let alice_account = spawn::<BankAccount>(("ALICE-001".to_string(), 1000.0));
142    let bob_account = spawn::<BankAccount>(("BOB-002".to_string(), 500.0));
143
144    // Perform some operations
145    println!("\n=== Initial Operations ===");
146    
147    // Check initial balances
148    let alice_balance = alice_account.ask_dyn(GetBalance).await?;
149    let bob_balance = bob_account.ask_dyn(GetBalance).await?;
150    println!("Alice: ${:.2}, Bob: ${:.2}", alice_balance, bob_balance);
151
152    // Alice deposits money
153    let _ = alice_account.ask_dyn(Deposit { amount: 200.0 }).await?;
154
155    // Bob withdraws money
156    let _ = bob_account.ask_dyn(Withdraw { amount: 100.0 }).await?;
157
158    println!("\n=== Transfer Operation ===");
159    
160    // Alice transfers money to Bob
161    alice_account.ask_dyn(Transfer { 
162        to_account: bob_account.clone(), 
163        amount: 300.0 
164    }).await?;
165
166    println!("\n=== Final Balances ===");
167    let alice_final = alice_account.ask_dyn(GetBalance).await?;
168    let bob_final = bob_account.ask_dyn(GetBalance).await?;
169    println!("Alice: ${:.2}, Bob: ${:.2}", alice_final, bob_final);
170
171    println!("\n=== Error Handling ===");
172    
173    // Try to withdraw more than available (should fail)
174    match alice_account.ask_dyn(Withdraw { amount: 2000.0 }).await {
175        Ok(_) => println!("Withdrawal succeeded unexpectedly!"),
176        Err(e) => println!("Withdrawal failed as expected: {}", e),
177    }
178
179    // Wait a moment before shutting down
180    sleep(Duration::from_millis(100)).await;
181
182    Ok(())
183}
examples/handler_pattern.rs (line 105)
95async fn main() -> anyhow::Result<()> {
96    println!("=== Handler Pattern Example ===\n");
97
98    // Spawn the actor
99    let actor = spawn::<MultiHandlerActor>("CounterBot".to_string());
100
101    // Use different message types with the same actor
102    println!("1. Testing typed messages:");
103    
104    // Increment counter
105    let count1: Result<i32, anyhow::Error> = actor.ask_dyn(IncrementMsg).await;
106    println!("Result: {:?}", count1);
107
108    let count2: Result<i32, anyhow::Error> = actor.ask_dyn(IncrementMsg).await;  
109    println!("Result: {:?}", count2);
110
111    // Get current count
112    let current: Result<i32, anyhow::Error> = actor.ask_dyn(GetCountMsg).await;
113    println!("Current count: {:?}", current);
114
115    println!("\n2. Testing name operations:");
116    
117    // Change name
118    let old_name: Result<String, anyhow::Error> = actor.ask_dyn(SetNameMsg("SuperBot".to_string())).await;
119    println!("Previous name: {:?}", old_name);
120
121    // Get current name
122    let name: Result<String, anyhow::Error> = actor.ask_dyn(GetNameMsg).await;
123    println!("Current name: {:?}", name);
124
125    println!("\n3. Testing dynamic string messages:");
126    
127    // Send string messages dynamically
128    let response1: Result<String, anyhow::Error> = actor.ask_dyn("Hello there!".to_string()).await;
129    println!("Response: {:?}", response1);
130
131    let response2: Result<String, anyhow::Error> = actor.ask_dyn("How are you doing?".to_string()).await;
132    println!("Response: {:?}", response2);
133
134    println!("\n4. Final state check:");
135    let final_count: Result<i32, anyhow::Error> = actor.ask_dyn(GetCountMsg).await;
136    let final_name: Result<String, anyhow::Error> = actor.ask_dyn(GetNameMsg).await;
137    println!("Final count: {:?}, Final name: {:?}", final_count, final_name);
138
139    Ok(())
140}
examples/worker_pool.rs (line 130)
93async fn main() -> anyhow::Result<()> {
94    println!("=== Worker Pool Example ===\n");
95    
96    // Create workers
97    let worker1 = spawn::<Worker>(1);
98    let worker2 = spawn::<Worker>(2);
99    let worker3 = spawn::<Worker>(3);
100    
101    // Submit several tasks to different workers
102    println!("Submitting tasks...\n");
103    
104    let tasks = vec![
105        ("Calculate prime numbers", 500),
106        ("Process image", 800),
107        ("Analyze data", 300),
108        ("Generate report", 1000),
109        ("Send email", 200),
110        ("Update database", 600),
111    ];
112    
113    // Submit tasks concurrently using tokio::spawn
114    let mut handles = vec![];
115    
116    for (i, (task_name, duration)) in tasks.into_iter().enumerate() {
117        let worker = match i % 3 {
118            0 => worker1.clone(),
119            1 => worker2.clone(),
120            _ => worker3.clone(),
121        };
122        
123        let handle = tokio::spawn(async move {
124            let task = Task {
125                id: (i + 1) as u32,
126                data: format!("{} #{}", task_name, i + 1),
127                processing_time_ms: duration,
128            };
129            
130            worker.ask_dyn(task).await
131        });
132        handles.push(handle);
133    }
134    
135    // Wait for all tasks to complete
136    println!("Waiting for all tasks to complete...\n");
137    for handle in handles {
138        match handle.await? {
139            Ok(result) => println!("✓ Task {} completed: {}", result.task_id, result.result),
140            Err(e) => println!("✗ Task failed: {}", e),
141        }
142    }
143    
144    // Get worker statistics
145    println!("\n=== Worker Statistics ===");
146    for worker in [&worker1, &worker2, &worker3] {
147        match worker.ask_dyn(GetWorkerStats).await {
148            Ok(stats) => println!("Worker {}: {} tasks processed", stats.worker_id, stats.tasks_processed),
149            Err(e) => println!("Failed to get stats: {}", e),
150        }
151    }
152    
153    println!("\n=== All tasks completed ===");
154    
155    // Wait a moment for any remaining output
156    sleep(Duration::from_millis(500)).await;
157    
158    Ok(())
159}
examples/dynamic_dispatch.rs (lines 186-189)
178async fn main() -> anyhow::Result<()> {
179    println!("=== Dynamic Dispatch Example ===\n");
180
181    let router = spawn::<RouterActor>(());
182
183    // Test typed message handlers
184    println!("1. Setting up routes:");
185    
186    let _: Result<bool, anyhow::Error> = router.ask_dyn(AddRouteRequest {
187        path: "/api/users".to_string(),
188        handler: "UserHandler".to_string(),
189    }).await;
190    
191    let _: Result<bool, anyhow::Error> = router.ask_dyn(AddRouteRequest {
192        path: "/api/posts".to_string(), 
193        handler: "PostHandler".to_string(),
194    }).await;
195
196    let _: Result<bool, anyhow::Error> = router.ask_dyn(AddRouteRequest {
197        path: "/health".to_string(),
198        handler: "HealthHandler".to_string(), 
199    }).await;
200
201    println!("\n2. Testing route lookups:");
202    
203    let response: Result<RouteResponse, anyhow::Error> = router.ask_dyn(GetRouteRequest {
204        path: "/api/users".to_string(),
205    }).await;
206    println!("Lookup result: {:?}", response);
207
208    let response: Result<RouteResponse, anyhow::Error> = router.ask_dyn(GetRouteRequest {
209        path: "/nonexistent".to_string(),
210    }).await;
211    println!("Lookup result: {:?}", response);
212
213    println!("\n3. Listing all routes:");
214    let routes: Result<Vec<(String, String)>, anyhow::Error> = router.ask_dyn(ListRoutesRequest).await;
215    println!("Routes: {:?}", routes);
216
217    println!("\n4. Testing dynamic string commands:");
218    
219    let help: Result<String, anyhow::Error> = router.ask_dyn("help".to_string()).await;
220    println!("Help response: {:?}", help);
221
222    let status: Result<String, anyhow::Error> = router.ask_dyn("status".to_string()).await;
223    println!("Status response: {:?}", status);
224
225    let echo: Result<String, anyhow::Error> = router.ask_dyn("echo Hello dynamic world!".to_string()).await;
226    println!("Echo response: {:?}", echo);
227
228    let unknown: Result<String, anyhow::Error> = router.ask_dyn("unknown command".to_string()).await;
229    println!("Unknown command response: {:?}", unknown);
230
231    println!("\n5. Final stats:");
232    let stats: Result<(u32, usize), anyhow::Error> = router.ask_dyn(StatsRequest).await;
233    println!("Final stats: {:?}", stats);
234
235    Ok(())
236}
Source

pub async fn send<T, R>(&self, message: T) -> R
where A: ActorLike<Message = Envelope<T, R>>, T: Send + Sync + 'static, R: Send + Sync + 'static + FromError<<<<A as ActorLike>::Channel as ActorChannel>::Sender as ActorSender<<<A as ActorLike>::Channel as ActorChannel>::Message>>::Error> + FromError<RecvError>,

Examples found in repository?
examples/echo_server.rs (line 40)
34async fn main() -> anyhow::Result<()> {
35    let echo_server = spawn::<EchoServer>(());
36
37    let messages = vec!["Hello", "World", "How are you?", "Goodbye"];
38
39    for message in messages {
40        let response: anyhow::Result<String> = echo_server.send(message.to_string()).await;
41        println!("Received: {}", response?);
42    }
43
44    Ok(())
45}
More examples
Hide additional examples
examples/basic_actor.rs (line 75)
70async fn main() -> anyhow::Result<()> {
71    // Spawn a counter actor with initial value 0
72    let counter = spawn::<Counter>(0);
73
74    // Send increment messages
75    counter.send(()).await?;
76    counter.send(()).await?;
77    counter.send(()).await?;
78
79    println!("Sent 3 increment messages");
80
81    // For demonstration, we'll just show that we can increment
82    // A real multi-message actor would use the Multi<A> pattern
83    // as shown in the integration tests
84
85    Ok(())
86}
examples/simple_counter.rs (line 60)
55async fn main() -> anyhow::Result<()> {
56    // Spawn a counter actor with initial value 0
57    let counter = spawn::<Counter>(0);
58
59    // Send increment messages
60    let _: anyhow::Result<CounterResponse> = counter.send(CounterRequest::Increment).await;
61    let _: anyhow::Result<CounterResponse> = counter.send(CounterRequest::Increment).await;
62    let _: anyhow::Result<CounterResponse> = counter.send(CounterRequest::Increment).await;
63
64    // Get the current count
65    let response: anyhow::Result<CounterResponse> = counter.send(CounterRequest::GetCount).await;
66    match response? {
67        CounterResponse::Count(count) => println!("Final count: {}", count),
68        _ => println!("Unexpected response"),
69    }
70
71    Ok(())
72}
Source

pub async fn send_raw( &self, message: A::Message, ) -> Result<(), <<<A as ActorLike>::Channel as ActorChannel>::Sender as ActorSender<<<A as ActorLike>::Channel as ActorChannel>::Message>>::Error>

Source

pub fn cancel(&self, reason: A::Cancel)

Source

pub async fn cancel_and_wait(&self, reason: A::Cancel)

Source

pub fn to_dyn<M>(&self) -> DynLink<M>
where M: Send + Sync + 'static, A: Handler<M> + ActorLike<Message = Multi<A>>,

Source§

impl<A: Actor> Link<A>

Source

pub fn downgrade(&self) -> WeakLink<A>

Trait Implementations§

Source§

impl<A: ActorLike> Clone for Link<A>

Source§

fn clone(&self) -> Self

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl<A: ActorLike> Debug for Link<A>
where A::State: Debug,

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl<A: ActorLike> Hash for Link<A>

Source§

fn hash<H: Hasher>(&self, state: &mut H)

Feeds this value into the given Hasher. Read more
1.3.0 · Source§

fn hash_slice<H>(data: &[Self], state: &mut H)
where H: Hasher, Self: Sized,

Feeds a slice of this type into the given Hasher. Read more
Source§

impl<A: ActorLike> PartialEq for Link<A>

Source§

fn eq(&self, other: &Self) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl<A: ActorLike> Eq for Link<A>

Auto Trait Implementations§

§

impl<A> Freeze for Link<A>

§

impl<A> !RefUnwindSafe for Link<A>

§

impl<A> Send for Link<A>

§

impl<A> Sync for Link<A>

§

impl<A> Unpin for Link<A>

§

impl<A> !UnwindSafe for Link<A>

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> Downcast for T
where T: Any,

Source§

fn into_any(self: Box<T>) -> Box<dyn Any>

Convert Box<dyn Trait> (where Trait: Downcast) to Box<dyn Any>. Box<dyn Any> can then be further downcast into Box<ConcreteType> where ConcreteType implements Trait.
Source§

fn into_any_rc(self: Rc<T>) -> Rc<dyn Any>

Convert Rc<Trait> (where Trait: Downcast) to Rc<Any>. Rc<Any> can then be further downcast into Rc<ConcreteType> where ConcreteType implements Trait.
Source§

fn as_any(&self) -> &(dyn Any + 'static)

Convert &Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &Any’s vtable from &Trait’s.
Source§

fn as_any_mut(&mut self) -> &mut (dyn Any + 'static)

Convert &mut Trait (where Trait: Downcast) to &Any. This is needed since Rust cannot generate &mut Any’s vtable from &mut Trait’s.
Source§

impl<T> DowncastSync for T
where T: Any + Send + Sync,

Source§

fn into_any_arc(self: Arc<T>) -> Arc<dyn Any + Send + Sync>

Convert Arc<Trait> (where Trait: Downcast) to Arc<Any>. Arc<Any> can then be further downcast into Arc<ConcreteType> where ConcreteType implements Trait.
Source§

impl<Q, K> Equivalent<K> for Q
where Q: Eq + ?Sized, K: Borrow<Q> + ?Sized,

Source§

fn equivalent(&self, key: &K) -> bool

Checks if this value is equivalent to the given key. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T> Instrument for T

Source§

fn instrument(self, span: Span) -> Instrumented<Self>

Instruments this type with the provided Span, returning an Instrumented wrapper. Read more
Source§

fn in_current_span(self) -> Instrumented<Self>

Instruments this type with the current Span, returning an Instrumented wrapper. Read more
Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.
Source§

impl<T> WithSubscriber for T

Source§

fn with_subscriber<S>(self, subscriber: S) -> WithDispatch<Self>
where S: Into<Dispatch>,

Attaches the provided Subscriber to this type, returning a WithDispatch wrapper. Read more
Source§

fn with_current_subscriber(self) -> WithDispatch<Self>

Attaches the current default Subscriber to this type, returning a WithDispatch wrapper. Read more