nbio/no-callbacks

Code

main.odin ¶
73 linesSource

1/*
2Example shows how you could poll completions instead of being pushed completions through callbacks.
3
4Completions are added to a queue by a single simple callback, and handled whenever wanted.
5
6It is a UDP echo server.
7*/
8package main
9
10import "core:container/queue"
11import "core:fmt"
12import "core:nbio"
13
14main :: proc() {
15	nbio.acquire_thread_event_loop()
16	defer nbio.release_thread_event_loop()
17
18	socket, err := nbio.create_udp_socket(.IP4)
19	if err != nil {
20		fmt.eprintfln("create_udp_socket: %v", err)
21		return
22	}
23	if err := nbio.bind(socket, {nbio.IP4_Loopback, 1234}); err != nil {
24		fmt.eprintfln("bind: %v", err)
25		return
26	}
27
28	buf: [1024]byte
29	nbio.recv(socket, {buf[:]}, queue_callback)
30
31	for {
32		fmt.println("tick")
33
34		for op in queue.pop_front_safe(&g_queue) {
35			defer nbio.reattach(op) // Releases ownership of the operation.
36
37			fmt.printfln("%v completed", op.type)
38
39			#partial switch op.type {
40			case .Recv:
41				if op.recv.err != nil {
42					fmt.eprintfln("recv: %v", op.recv.err)
43					nbio.recv(socket, {buf[:]}, queue_callback)
44					continue
45				}
46
47				fmt.printfln("received %M", op.recv.received)
48				nbio.send(socket, {buf[:op.recv.received]}, queue_callback, op.recv.source)
49
50			case .Send:
51				if op.send.err != nil {
52					fmt.eprintfln("send: %v", op.send.err)
53				}
54				fmt.printfln("sent %M", op.send.sent)
55				nbio.recv(socket, {buf[:]}, queue_callback)
56
57			case:
58				fmt.eprintfln("unimplemented: %v", op.type)
59			}
60		}
61
62		if err := nbio.tick(); err != nil {
63			fmt.eprintfln("tick: %v", err)
64		}
65	}
66}
67
68g_queue: queue.Queue(^nbio.Operation)
69
70queue_callback :: proc(op: ^nbio.Operation) {
71	nbio.detach(op) // Takes ownership of the operation.
72	queue.push_back(&g_queue, op)
73}

Declarations Used 17