From 2609c2ca2fa85ab027af772cae74af5d4ecb25cf Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Wed, 30 Nov 2022 13:23:29 +0100 Subject: [PATCH] Flesh out dispatch --- ev/+linux/file.ha | 2 +- ev/+linux/io.ha | 22 ++++++++++++++++++++-- ev/+linux/loop.ha | 31 +++++++++++++++++++++++-------- diff --git a/ev/+linux/file.ha b/ev/+linux/file.ha index a4ef4e35ff5dae63e340ba4ceb9678b8c790ec9f..01db94908217af2725d8921b9c1b1a6362015d86 100644 --- a/ev/+linux/file.ha +++ b/ev/+linux/file.ha @@ -13,7 +13,7 @@ fd: io::file, ev: *loop, // Pending operation on this file object op: op, - callback: nullable *void, + cb: nullable *void, // Operation-specific data vbuf: rt::iovec, diff --git a/ev/+linux/io.ha b/ev/+linux/io.ha index 3c72ee857910c88ac9259a4884899e761131e924..0e20b4d468d2049f221c6076856914f779be0153 100644 --- a/ev/+linux/io.ha +++ b/ev/+linux/io.ha @@ -24,10 +24,19 @@ vec: io::vector... ) req = { assert(file.op == op::NONE); file.op = op::READV; - file.callback = cb; + file.cb = cb; file.vec = vec; filemod(file, rt::EPOLLOUT); return req { ... }; +}; + +fn readv_finish(file: *file, ev: *rt::epoll_event) void = { + assert(file.op == op::READV && ev.events & rt::EPOLLIN != 0); + assert(file.cb != null); + const r = io::readv(file.fd, file.vec...); + const cb = file.cb: *readcb; + cb(file, r); + file.op = op::NONE; }; // A callback for a [[write]] or [[writev]] operation. @@ -55,8 +64,17 @@ // XXX: Should we support both pending reads and writes at the same // time? (yes) assert(file.op == op::NONE); file.op = op::WRITEV; - file.callback = cb; + file.cb = cb; file.vec = vec; filemod(file, rt::EPOLLOUT); return req { ... }; }; + +fn writev_finish(file: *file, ev: *rt::epoll_event) void = { + assert(file.op == op::WRITEV && ev.events & rt::EPOLLOUT != 0); + assert(file.cb != null); + const r = io::writev(file.fd, file.vec...); + const cb = file.cb: *writecb; + cb(file, r); + file.op = op::NONE; +}; diff --git a/ev/+linux/loop.ha b/ev/+linux/loop.ha index f3492ffaa4d2a8d5c341d4fb3f4c8782bc6acbf2..17f658f30a787306a38c8c59004bbffc7c2562f9 100644 --- a/ev/+linux/loop.ha +++ b/ev/+linux/loop.ha @@ -39,8 +39,9 @@ export fn loop_file(loop: *loop) io::file = { return loop.fd; }; -// Dispatches the event loop. A duration of -1 specifies an indefinite timeout, -// and will cause dispatch to block until the next event is available. +// Dispatches the event loop. A timeout of 0 specifies an indefinite timeout, +// and will cause dispatch to block until the next event is available. A timeout +// of -1 will return immediately if no events are available. // // Portable use of the timeout argument supports only millisecond granularity of // up to 24 days (INT_MAX milliseconds). Negative values other than -1 will @@ -65,10 +66,24 @@ // TODO: Deal with signals const maxev = len(loop.events); assert(maxev <= types::INT_MAX: size, "ev::dispatch: too many events"); const events = rt::epoll_pwait( - loop.fd, - &loop.events[0], - maxev: int, - millis, - null)!; - return true; + loop.fd, &loop.events[0], + maxev: int, millis, null)!; + + for (let i = 0z; i < maxev; i += 1) { + const ev = &loop.events[i]; + const file = ev.data.ptr: *file; + if (ev.events == 0) { + continue; + }; + switch (file.op) { + case op::NONE => + abort("Invalid pending operation"); + case op::READV => + readv_finish(file, ev); + case op::WRITEV => + writev_finish(file, ev); + }; + }; + + return events != 0; }; -- 2.48.1