1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
use std::{
  time::Duration,
  vec::*,
};

use ferrite_session::prelude::*;
use tokio::time::sleep;

pub fn concat_session() -> Session<End>
{
  let p1: Session<
    ReceiveValue<
      Vec<String>,
      ReceiveValue<Vec<String>, SendValue<String, End>>,
    >,
  > = receive_value(|l1: Vec<String>| {
    println!("[P1] Received first list: [{}]", l1.join(", "));

    receive_value(|l2: Vec<String>| {
      println!("[P1] Received second list: [{}]", l2.join(", "));

      step(async move {
        send_value(
          {
            println!("[P1] Spending 3 seconds to concat lists");
            sleep(Duration::from_secs(3)).await;

            let l5 = {
              let mut l3 = l1;
              let mut l4 = l2;
              l3.append(&mut l4);
              l3
            };

            l5.join(", ")
          },
          terminate_async(|| async {
            println!("[P1] Spending 2 seconds to cleanup");
            sleep(Duration::from_secs(2)).await;
            println!("[P1] Terminating");
          }),
        )
      })
    })
  });

  let p2: Session<
    ReceiveChannel<
      ReceiveValue<
        Vec<String>,
        ReceiveValue<Vec<String>, SendValue<String, End>>,
      >,
      End,
    >,
  > = receive_channel(|val_chan| {
    step(async move {
      send_value_to(
        val_chan,
        {
          println!("[P2] spending 2 seconds to produce ['hello', 'world']");
          sleep(Duration::from_secs(2)).await;

          vec!["hello".to_string(), "world".to_string()]
        },
        step(async move {
          send_value_to(
            val_chan,
            {
              println!(
                "[P2] spending 1 second to produce ['foo', 'bar', 'baz']"
              );
              sleep(Duration::from_secs(1)).await;

              vec!["foo".to_string(), "bar".to_string(), "baz".to_string()]
            },
            receive_value_from(val_chan, move |res| {
              println!("[P2] received result from P1: [{}]", res);

              wait(val_chan, {
                println!("[P2] P1 has terminated");

                terminate_async(|| async {
                  println!("[P2] Spending 1 second to cleanup");
                  sleep(Duration::from_secs(1)).await;
                  println!("[P2] Terminating");
                })
              })
            }),
          )
        }),
      )
    })
  });

  apply_channel(p2, p1)
}

#[tokio::main]
pub async fn main()
{
  run_session(concat_session()).await;
}