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:
|
type private Process =
{ Name: string
ChanSend: Channel<int>
ChanRecv: Channel<int>
}
let private createSendProcess chanSend chanRecv value name m =
let rec create n =
if n = 1 then
Send(value, chanSend, fun () ->
printfn $"%s{name} sent: %A{value}"
Receive(chanRecv, fun v ->
printfn $"%s{name} received: %A{v}"
End()))
else
Send(value, chanSend, fun () ->
printfn $"%s{name} sent: %A{value}"
Receive(chanRecv, fun v ->
printfn $"%s{name} received: %A{v}"
create (n - 1)))
create m
let private createRecvProcess chanRecv chanSend name m =
let rec create n =
if n = 1 then
Receive(chanRecv, fun v ->
printfn $"%s{name} received: %A{v}"
let value = v + 10
Send(value, chanSend, fun () ->
printfn $"%s{name} sent: %A{value}"
End()))
else
Receive(chanRecv, fun v ->
printfn $"%s{name} received: %A{v}"
let value = v + 10
Send(value, chanSend, fun () ->
printfn $"%s{name} sent: %A{value}"
create (n - 1)))
create m
let processRing processCount roundCount =
let getRecvChan index (chans : Channel<int> list) =
match index with
| i when i - 1 < 0 -> chans.Item (List.length chans - 1)
| i -> chans.Item (i - 1)
let rec createProcesses chans allChans index acc =
match chans with
| [] -> acc
| c::cs -> let proc = {Name = $"p{index}"; ChanSend = c; ChanRecv = getRecvChan index allChans}
createProcesses cs allChans (index + 1) (acc @ [proc])
let rec createProcessRing procs index m =
match procs with
| pa::pb::[] when index = 0 -> Parallel(createSendProcess pa.ChanSend pa.ChanRecv 0 pa.Name m, createRecvProcess pb.ChanRecv pb.ChanSend pb.Name m, fun _ -> End())
| pa::pb::[] -> Parallel(createRecvProcess pa.ChanRecv pa.ChanSend pa.Name m, createRecvProcess pb.ChanRecv pb.ChanSend pb.Name m, fun _ -> End())
| p::ps when index = 0 -> Parallel(createSendProcess p.ChanSend p.ChanRecv 0 p.Name m, createProcessRing ps (index + 1) m, fun _ -> End())
| p::ps -> Parallel(createRecvProcess p.ChanRecv p.ChanSend p.Name m, createProcessRing ps (index + 1) m, fun _ -> End())
| _ -> failwith $"createProcessRing failed! m = %A{m}"
let chans = [for _ in 1..processCount -> Channel<int>()]
let processes = createProcesses chans chans 0 []
createProcessRing processes 0 roundCount
|