Files
@ 8ea9f0e9a5ab
Branch filter:
Location: CSY/reowolf/testdata/parser/positive/tarry.pdl
8ea9f0e9a5ab
4.8 KiB
text/plain
fusing ports and keys
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 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 | #version 100
/*
Example distributed algorithm: Tarry's algorithm.
A token passes around the network, starting at some initiator. The initiator
starts the algorithm, and when the algorithm ends the token is back again at
the initiator. The non-initiators are signaled when they receive the token
for the first time; when the token is handled traversal continues.
The network topology is defined by applications: they create an initiator or
non-initiator component, and establish bidirectional channels in between.
In this example, the whole network is created statically for simulation
purposes: there are 4 processes and some channels in between.
Ports: initiator start, initiator end, three pairs of signals.
*/
import std.reo;
composite main(in start, out end, out s1o, in s1i, out s2o, in s2i, out s3o, in s3i) {
// Processes: p, q, r, s
// Channels: pq, pr, qr, rs
channel p_pq -> pq_q;
channel q_pq -> pq_p;
channel p_pr -> pr_r;
channel r_pr -> pr_p;
channel q_qr -> qr_r;
channel r_qr -> qr_q;
channel r_rs -> rs_s;
channel s_rs -> rs_r;
new initiator(start, end, {pq_p, pr_p}, {p_pq, p_pr});
new noninitiator(s1o, s1i, {pq_q, qr_q}, {q_pq, q_qr});
new noninitiator(s2o, s2i, {pr_r, rs_r}, {r_pr, r_rs});
new noninitiator(s3o, s3i, {rs_s}, {s_rs});
}
primitive initiator(in start, out end, in[] peeri, out[] peero) {
msg token = null;
in[] neighbori = {};
out[] neighboro = {};
assert peeri.length == peero.length;
while (true) {
// Step 1. Initiator waits for token
while (token == null) {
synchronous {
if (fires(start)) {
token = get(start);
}
}
}
// Reset neighbors
neighbori = peeri;
peeri = {};
neighboro = peero;
peero = {};
// Step 2. Keep sending token to processes
while (neighbori.length > 0) {
int idx = 0;
// Select first channel that accepts our token
while (token != null) {
synchronous {
int i = 0;
while (i < neighboro.length) {
if (fires(neighboro[i])) {
put(neighboro[i], token);
idx = i;
token = null;
break;
} else i++;
}
}
}
// Eliminate from neighbor set
peeri = {neighbori[idx]} @ peeri;
peero = {neighboro[idx]} @ peero;
neighbori = neighbori[0:idx] @ neighbori[idx:neighbori.length];
neighboro = neighboro[0:idx] @ neighboro[idx:neighboro.length];
// Step 3. Await return of token
while (token == null) {
synchronous {
int i = 0;
while (i < peeri.length + neighbori.length) {
if (fires(peeri@neighbori[i])) {
token = get(peeri@neighbori[i]);
break;
} else i++;
}
}
}
}
// Step 4. Token is back and all neighbors visited
while (token != null) {
synchronous {
if (fires(end)) {
put(end, token);
token = null;
}
}
}
}
}
primitive noninitiator(out start, in end, in[] peeri, out[] peero) {
msg token = null;
in[] neighbori = {};
out[] neighboro = {};
in[] parenti = {};
out[] parento = {};
assert peeri.length == peero.length;
while (true) {
int idx = 0;
// Step 1. Await token for first time
while (token == null) {
synchronous {
int i = 0;
while (i < peeri.length) {
if (fires(peeri[i])) {
token = get(peeri[i]);
idx = i;
break;
} else i++;
}
}
}
// Reset neighbors
neighbori = peeri[0:idx] @ peeri[idx:peeri.length];
neighboro = peero[0:idx] @ peero[idx:peero.length];
parenti = {peeri[idx]};
parento = {peero[idx]};
peeri = {};
peero = {};
// Step 2. Non-initiator signals
while (token != null) {
synchronous {
if (fires(end)) {
put(end, token);
token = null;
}
}
}
while (token == null) {
synchronous {
if (fires(start)) {
token = get(start);
}
}
}
// Step 3. Keep sending token to processes
while (neighbori.length > 0) {
idx = 0;
// Select first channel that accepts our token
while (token != null) {
synchronous {
int i = 0;
while (i < neighboro.length) {
if (fires(neighboro[i])) {
put(neighboro[i], token);
idx = i;
token = null;
break;
} else i++;
}
}
}
// Eliminate from neighbor set
peeri = {neighbori[idx]} @ peeri;
peero = {neighboro[idx]} @ peero;
neighbori = neighbori[0:idx] @ neighbori[idx:neighbori.length];
neighboro = neighboro[0:idx] @ neighboro[idx:neighboro.length];
// Step 4. Await return of token
while (token == null) {
synchronous {
int i = 0;
while (i < peeri.length + neighbori.length) {
if (fires(peeri@neighbori[i])) {
token = get(peeri@neighbori[i]);
break;
} else i++;
}
}
}
}
// Step 5. Token is back, pass to parent
while (token != null) {
synchronous {
if (fires(parento[0])) {
put(parento[0], token);
token = null;
}
}
}
peeri = {parenti[0]} @ peeri;
peero = {parento[0]} @ peero;
parenti = {};
parento = {};
}
}
|