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}