exercises

Unnamed repository; edit this file 'description' to name the repository.
Log | Files | Refs | README

main.rs (3526B)


      1 //! Actors are easier to conceptualize.
      2 //! Actors contain their state. If you want to see all interactions with
      3 //! that state, you look in the actor code.
      4 //! However, with mutex codebases, we do not know where all the
      5 //! interactions with the states are, which could make it harder
      6 //! to maintain.
      7 
      8 use std::sync::Arc;
      9 
     10 use actor_model::{
     11     basic_actor::{Message, RespMessage, basic_actor, resp_actor},
     12     mutex_replacement::actor_replacement,
     13 };
     14 use tokio::sync::{Mutex, mpsc::channel, oneshot};
     15 
     16 #[tokio::main]
     17 async fn main() {
     18     // 1. Basic actor without responder
     19     // let (tx, rx) = channel::<Message>(100);
     20 
     21     // let _actor_handle = tokio::spawn(basic_actor(rx));
     22 
     23     // for i in 0..10 {
     24     //     let msg = Message { value: i };
     25     //     tx.send(msg).await.unwrap();
     26     // }
     27 
     28     // 2. Basic actor with responder
     29     // if we want to send a message to our responding actor, we need to
     30     // construct a onshot channel.
     31     let (tx, rx) = channel::<RespMessage>(100);
     32 
     33     let _resp_actor_handle = tokio::spawn(async {
     34         resp_actor(rx).await;
     35     });
     36 
     37     for i in 0..10 {
     38         // We use a oneshot channel because we need the response to be
     39         // sent only once and then close; after that the client code
     40         // can go about doing other things.
     41         let (resp_tx, resp_rx) = oneshot::channel::<i64>();
     42 
     43         let msg = RespMessage {
     44             value: i,
     45             responder: resp_tx,
     46         };
     47         tx.send(msg).await.unwrap();
     48         // do something else after sending the message and waiting
     49         // for the response, without needing to spawn async tasks.
     50         // this flexibility of choosing when to wait for the result
     51         // of the message comes for free withg actors.
     52         println!("Response: {}", resp_rx.await.unwrap());
     53     }
     54 
     55     // 3.1 Actor replacement using mutex: Elapsed: 602.618µs
     56     // let state = Arc::new(Mutex::new(0));
     57     // let mut handles = Vec::new();
     58 
     59     // let now = tokio::time::Instant::now();
     60 
     61     // for i in 0..100 {
     62     //     let state_ref = state.clone();
     63     //     let future = async move {
     64     //         let handle = tokio::spawn(async move { actor_replacement(state_ref, i).await });
     65 
     66     //         let _ = handle.await.unwrap();
     67     //     };
     68     //     handles.push(tokio::spawn(future));
     69     // }
     70     // for handle in handles {
     71     //     let _ = handle.await.unwrap();
     72     // }
     73     // println!("Elapsed: {:?}", now.elapsed());
     74 
     75     // 3.2 Actor approach: Elapsed: 313.017µs
     76     //
     77     // Generally, passing messages through channels can scale better than
     78     // mutexes in concurrent environments, because the senders do not
     79     // have to wait for other tasks to finish what they are doing.
     80     // let (tx, rx) = channel::<RespMessage>(100);
     81     // let _resp_actor_handle = tokio::spawn(async {
     82     //     resp_actor(rx).await;
     83     // });
     84 
     85     // let mut handles = Vec::new();
     86 
     87     // let now = tokio::time::Instant::now();
     88     // for i in 0..100 {
     89     //     let tx_ref = tx.clone();
     90 
     91     //     let future = async move {
     92     //         let (resp_tx, resp_rx) = oneshot::channel::<i64>();
     93     //         let msg = RespMessage {
     94     //             value: i,
     95     //             responder: resp_tx,
     96     //         };
     97     //         tx_ref.send(msg).await.unwrap();
     98     //         let _ = resp_rx.await.unwrap();
     99     //     };
    100     //     handles.push(tokio::spawn(future));
    101     // }
    102     // for handle in handles {
    103     //     handle.await.unwrap();
    104     // }
    105     // println!("Elapsed: {:?}", now.elapsed());
    106 }