Landin library reference discuss source

compiler/tests/fixtures/runtime/events-tcp-exchange/main.ldn

1--  D485: two fibres exchanging over a loopback TCP connection
2--  under hosted/events.  The server accepts and the client connects; each
3--  message is answered before the next is sent, so their lines can only
4--  interleave as the provider lets one fibre run while the other waits in
5--  `receive`.  The home stack joins the group, waiting in the loop.
6import core/failure
7import core/fibre
8import core/io
9import core/net
10import hosted/events
11
12mut trace: [64]u8 = zeroed
13mut marks: usize = 0
14
15--  Note one step: a letter and a digit, after a space from the last.
16mark: (letter: u8, digit: usize) -> none =
17    if marks > 0 then
18        trace[marks] = u8(' ')
19        inc marks
20    end if
21    trace[marks] = letter
22    trace[marks + 1] = u8('0') + u8(digit)
23    marks += 2
24end mark
25
26serving: type = struct
27    host: events.host
28    listener: io.file
29end serving
30
31--  Accept one connection and answer three messages, each with its
32--  number doubled.
33serve: (inout state: serving) -> none ! failure.reason =
34    connection: io.file = try net.accept(state.host, state.listener)
35    mut buffer: [1]u8 = zeroed
36    for round in usize(0)..<3 do
37        got: usize = try net.receive(state.host, connection, buffer)
38        fail io.io_failed when got <> 1
39        mark(u8('s'), usize(buffer[0]))
40        buffer[0] = buffer[0] * 2
41        try net.send(state.host, connection, buffer)
42        _ = round
43    end for
44    try net.close_socket(state.host, connection)
45end serve
46
47asking: type = struct
48    host: events.host
49    peer: net.address
50end asking
51
52--  Connect and send three messages, waiting for each answer.
53ask: (inout state: asking) -> none ! failure.reason =
54    connection: io.file = try net.connect(state.host, state.peer)
55    mut buffer: [1]u8 = zeroed
56    for round in usize(1)..<4 do
57        buffer[0] = u8(round)
58        mark(u8('c'), round)
59        try net.send(state.host, connection, buffer)
60        got: usize = try net.receive(state.host, connection, buffer)
61        fail io.io_failed when got <> 1
62        mark(u8('a'), usize(buffer[0]))
63    end for
64    got: usize = try net.receive(state.host, connection, buffer)
65    fail io.io_failed when got <> 0
66    try net.close_socket(state.host, connection)
67end ask
68
69mut backing: [2 * 32768]u8 = zeroed
70
71run: (host: events.host) -> none ! failure.reason =
72    listener: io.file = try net.listen(host, net.loopback(net.ipv4, 0))
73    peer: net.address = try net.local_address(host, listener)
74    mut tasks := try fibre.turns_over(any(addr host), backing, 2)
75    defer fibre.join(tasks) else none
76    server: serving = (host: host, listener: listener)
77    try fibre.admit(tasks, serve, server)
78    client: asking = (host: host, peer: peer)
79    try fibre.admit(tasks, ask, client)
80    try fibre.join(tasks)
81    try net.close_socket(host, listener)
82    try io.write(host, io.out(host), trace[0..<marks])
83    try io.write(host, io.out(host), "\n")
84end run
85
86public main: () -> (code: i32) =
87    code = 1
88    mut state: events.space = zeroed
89    mut entries: [3]usize = zeroed
90    host := events.new(state, entries) else (problem)
91        _ = problem
92        return
93    end
94    code = 2
95    run(host) else (problem)
96        _ = problem
97        return
98    end
99    code = 0
100end main