From 9c31e89630080df375363482fe9e9938b66b43f5 Mon Sep 17 00:00:00 2001 From: Drew DeVault Date: Fri, 20 Oct 2023 09:16:30 +0200 Subject: [PATCH] add ev::do --- ev/+linux/loop.ha | 50 ++++++++++++++++++++++++++++++++++++++++++++++++++ diff --git a/ev/+linux/loop.ha b/ev/+linux/loop.ha index 06c04c3ec127358874129b5a16f65de2bc420b72..2716907f3136a3fac8eed173ca933da3e1632e82 100644 --- a/ev/+linux/loop.ha +++ b/ev/+linux/loop.ha @@ -5,9 +5,19 @@ use time; use types; use unix::signal; +// Dispatch callback. See [[ondispatch]]. +export type dispatchcb = fn(loop: *loop, user: nullable *opaque) void; + +export type ondispatch = struct { + cb: *dispatchcb, + user: nullable *opaque, + loop: *loop, +}; + export type loop = struct { fd: io::file, events: []rt::epoll_event, + dispatch: []*ondispatch, stop: bool, }; @@ -30,6 +40,7 @@ data = rt::epoll_data { fd = 0, } }...], 256), + dispatch = [], stop = false, }; }; @@ -50,6 +61,35 @@ export fn loop_file(loop: *loop) io::file = { return loop.fd; }; +// Registers a callback to be invoked before the event loop dispatches pending +// I/O requests. The callback may schedule additional I/O requests to be +// processed in this batch. +export fn do( + loop: *loop, + cb: *dispatchcb, + user: nullable *opaque, +) req = { + const dispatch = alloc(ondispatch { + cb = cb, + user = user, + loop = loop, + }); + append(loop.dispatch, dispatch); + return mkreq(&do_cancel, dispatch); +}; + +fn do_cancel(req: *req) void = { + const dispatch = req.user: *ondispatch; + const loop = dispatch.loop; + for (let i = 0z; i < len(loop.dispatch); i += 1) { + if (loop.dispatch[i] == dispatch) { + delete(loop.dispatch[i]); + break; + }; + }; + free(dispatch); +}; + // Dispatches the event loop, waiting for new events and calling their callbacks // as appropriate. // @@ -74,6 +114,16 @@ }; if (loop.stop) { return false; }; + + let todo = loop.dispatch; + loop.dispatch = []; + for (let i = 0z; i < len(todo); i += 1) { + const dispatch = todo[i]; + dispatch.cb(loop, dispatch.user); + free(dispatch); + }; + free(todo); + if (len(loop.events) == 0) { return true; }; -- 2.48.1