Skip to content

Commit 63574ab

Browse files
committed
Add Poll.swift
Implementation of `poll_oneoff` in WebAssembly System Interface standard (https://github.com/WebAssembly/WASI/blob/main/legacy/preview1/docs.md#poll_oneoff) can be approximated in operating systems implementing POSIX standard with `poll` (https://www.unix.com/man_page/posix/2/ppoll). This change adds such approximation, converting clock subscriptions using nanoseconds to milliseconds, while mapping file descriptor read and write subscriptions to `POLLIN` and `POLLOUT` events in POSIX.
1 parent f9d647b commit 63574ab

File tree

1 file changed

+46
-0
lines changed

1 file changed

+46
-0
lines changed

Sources/WASI/Poll.swift

Lines changed: 46 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,46 @@
1+
#if canImport(Darwin)
2+
import Darwin
3+
#elseif canImport(Glibc)
4+
import Glibc
5+
#elseif canImport(Musl)
6+
import Musl
7+
#elseif canImport(Android)
8+
import Android
9+
#else
10+
#error("Unsupported Platform")
11+
#endif
12+
13+
import SystemPackage
14+
15+
extension FdTable {
16+
func fileDescriptor(fd: WASIAbi.Fd) throws -> FileDescriptor {
17+
guard case let .file(entry) = self[fd], let fd = (entry as? FdWASIEntry)?.fd else {
18+
throw WASIAbi.Errno.EBADF
19+
}
20+
21+
return fd
22+
}
23+
}
24+
25+
func poll(
26+
subscriptions: some Sequence<WASIAbi.Subscription>,
27+
_ fdTable: FdTable
28+
) throws {
29+
var pollfds = [pollfd]()
30+
var timeoutMilliseconds = UInt.max
31+
32+
for subscription in subscriptions {
33+
let union = subscription.union
34+
switch union {
35+
case .clock(let clock):
36+
timeoutMilliseconds = min(timeoutMilliseconds, .init(clock.timeout / 1_000_000))
37+
case .fdRead(let fd):
38+
pollfds.append(.init(fd: try fdTable.fileDescriptor(fd: fd).rawValue, events: .init(POLLIN), revents: 0))
39+
case .fdWrite(let fd):
40+
pollfds.append(.init(fd: try fdTable.fileDescriptor(fd: fd).rawValue, events: .init(POLLOUT), revents: 0))
41+
42+
}
43+
}
44+
45+
poll(&pollfds, .init(pollfds.count), .init(timeoutMilliseconds))
46+
}

0 commit comments

Comments
 (0)