Commit graph

4 commits

Author SHA1 Message Date
Sofia Rodrigues
f9adafe54d
feat: adds acceptSelector and modified selectors (#10667)
This PR adds more selectors for TCP and Signals.

It also fixes a problem with `Selectors` that they cannot be closures
over a promise, otherwise it causes the waiter promise to never be
dropped.
2025-10-17 14:53:46 +00:00
Sofia Rodrigues
4881c3042e
refactor: replace Task with Async and minor changes to some basic Async functions (#10366)
This PR refactors the Async module to use the `Async` type in all of the
`Async` files.
2025-09-20 16:23:06 +00:00
Henrik Böving
c5f2c192d6
fix: Selectable.one does not panic on empty array (#10216)
This PR fixes #10193.
2025-09-02 11:55:36 +00:00
Henrik Böving
58c7e5da94
feat: async IO multiplexing framework + implementation for timers (#8055)
This PR adds an implementation of an async IO multiplexing framework as
well as an implementation of it for the `Timer` API in order to
demonstrate it.

The main motivation is to have fair and data loss free multiplexing of
event sources.
To illustrate two situations where just naively racing two tasks that
read from an event source might be the wrong thing:
1. Suppose we are waiting on two channel reads that are continuously
being filled up. As the first channel will always be ready when we start
its receive function it will instantly resolve the race before the
second one can even try. Thus the path where we receive data from the
second channel gets starved. For this reason we want to try in random
order (for fairness) if the event sources already have data available
for us.
2. Suppose we are waiting on two socket reads and both happen to finish
at the same time. As we are now only going to select one of them to
execute further, we are going to loose data on the second one (unless
there is a user written buffering mechanism involved) as we are going to
disregard the buffer it received and do a new receive next time. For
this reason it is important to wait for an event source to be available
without committing to actually fetching some data until we know that
this particular event source is going to win the select race.

The implementation is inspired by the Oslo framework written by
@haesbaert as well as Go's
[`select`](https://go.dev/src/runtime/select.go) implementation. Given a
list of event sources to select one from it is going to:
1. Randomly shuffle them
2. Attempt to fetch data from them (in their new random order) without
blocking (for fairness). If any of them succeeds return right away.
3. If none has data available right away set all of them up to resolve a
promise. They will then race to win the right to resolve that promise.
Only the data source that wins the race is allowed to then actually
fetch data, ensuring that no other event source actually fetches data
and then fails to deliver it to the consumer.


Follow up PRs are going to add implementations of `Selector` for
`Std.Channel` as well as TCP and UDP sockets.

---------

Co-authored-by: Markus Himmel <markus@lean-fro.org>
2025-04-24 07:55:39 +00:00