Skip to main content

storage_cell/
storage-cell.rs

1use rusty_junctions::Junction;
2
3fn main() {
4    /* Start of the Join Pattern setup. */
5
6    // Declare a new Junction to create new channels and construct new
7    // Join Patterns based on them.
8    let cell = Junction::new();
9
10    // New channel to retrieve the value of the storage cell.
11    let get = cell.recv_channel::<i32>();
12
13    // New channel to update the value of the storage cell.
14    let put = cell.send_channel::<i32>();
15
16    // New channel to swap the value of the storage cell for a new one and
17    // retrieve the value that was just replaced.
18    let swap = cell.bidir_channel::<i32, i32>();
19
20    // New channel that will actually carry the value so that at no point
21    // any given thread will have possession over it so concurrency issues
22    // are avoided by design.
23    let val = cell.send_channel::<i32>();
24
25    // Set up some clones of the above channels we can move over to the
26    // thread in which the function body of the Join Pattern will run.
27    //
28    // Clones of channels work like clones of the std::sync::mpsc::Sender
29    // clones - any message sent from the clone will be received as if
30    // sent from the original.
31    let get_val = val.clone();
32    let put_val = val.clone();
33    let swap_val = val.clone();
34    let val_val = val.clone();
35
36    // Declare a new Join Pattern to update the storage cell value. If
37    // both the put and val channel have sent a message, meaning someone
38    // requested a value update and there is a value to be updated, send
39    // a new val message through one of val's clones that carries the
40    // updated value.
41    cell.when(&put).and(&val).then_do(move |new, _old| {
42        println!(">> put-val pattern fired with new={}!", new);
43        put_val.send(new).unwrap();
44    });
45
46    // Declare a new Join Pattern to retrieve the storage cell value. If
47    // both the get and val channel have sent a message, meaning someone
48    // requested the value and there is a value to be given, return that
49    // value and resend it through one of val's clones so that the value
50    // is still available in future and not just consumed once.
51    cell.when(&val).and_recv(&get).then_do(move |v| {
52        println!(">> val-get pattern fired with v={}!", v);
53
54        get_val.send(v.clone()).unwrap();
55
56        v
57    });
58
59    // Declare a new Join Pattern to swap the storage cell value with a
60    // new one and retrieve the old. Essentially works like a combination
61    // of the previous two Join Patterns, with one crucial distinction:
62    // with this Join Pattern, the update of the value and the retrieval
63    // of the old are atomic, meaning that it is guaranteed that even in
64    // a multithreaded environment with many users accessing the storage
65    // cell, the value retrieved is exactly the value that has been
66    // updated.
67    cell.when(&val).and_bidir(&swap).then_do(move |old, new| {
68        println!(
69            ">> val-swap pattern fired with old={} and new={}!",
70            old, new
71        );
72        swap_val.send(new).unwrap();
73
74        old
75    });
76
77    // Declare a new Join Pattern that mentions the same channel multiple
78    // times, so if the val channel has sent two messages they will be
79    // combined into a single messages sent by a clone of val. This ensures
80    // that eventually, the storage cell will only keep a single value
81    // around.
82    cell.when(&val).and(&val).then_do(move |a, b| {
83        println!(">> val-val pattern fired with a={} and b={}!", a, b);
84        val_val.send(a + b).unwrap();
85    });
86
87    /* End of the Join Pattern setup. */
88
89    // Initialise the storage cell by sending an initial value that
90    // can be picked up in future executions of the above Join Patterns.
91    val.send(1729).unwrap();
92
93    // Request a value update if one is available.
94    put.send(42).unwrap();
95
96    // Send another value that will eventually get combined with the
97    // existing one.
98    val.send(1).unwrap();
99
100    // Request another value update.
101    put.send(22).unwrap();
102
103    // Request the current value of the storage cell and print it.
104    println!("get.recv()={}", get.recv().unwrap());
105
106    // Request a swap of the current value of the storage cell with a new
107    // one and print the old value that is retrieved as a result.
108    println!("swap.send_recv()={}", swap.send_recv(16).unwrap());
109
110    // Request the current value of the storage cell again and print it.
111    println!("get.recv()={}", get.recv().unwrap());
112}