I’m new to concurrency programming in OCaml and I’m currently playing with Eio streams, which I understand are similar to channels in Go.
In Go, if I have multiple channels to receive from, I would use select like this:
select {
case e1 := <-c1:
handleEvent(e1)
case e2 := <-c2:
handleEvent(e2)
}
My understanding is that with Eio, I’d use Fiber.any instead of select:
Fiber.any [
(fun () -> let e1 = Stream.take s1 in handle_event e1);
(fun () -> let e2 = Stream.take s2 in handle_event e2);
]
What’s confusing me is that, in the Eio documentation, it’s stated that:
Warning: it is always possible that both operations will succeed. This is because there is a period of time after the first operation succeeds when it is waiting in the run-queue to resume during which the other operation may also succeed.
But if that’s the case, how am I supposed to ensure that, if both operations succeed, then both handle_event run to completion? For example, say the following happens:
- Stream
s1yields first, sohandle_event e1runs - Stream
s2yields at the same time, sohandle_event e2also runs handle_event e2yields internally waiting for some IOFiber.anytries to cancel the second fiber becausehandle_event e1has returned
In this case, it sounds like handle_event s2 would be interrupted. But now, an event has been taken from s2, but handle_event s2 never ran to completion because it was cancelled by Fiber.any.
Could this happen? If so, how do I ensure safety with my concurrent code, so that event handlers are never interrupted before they could run to completion? Note that this could not happen in Go because select always receives from one channel only.