Understanding cancellation (in eio)

Not what you wish I’m afraid, but here’s how I believe you would go to implement it with affect (announced here).

IIUC, this happy eyeball algorithm just starts the tasks of a list every delay seconds and returns the first one that succeeds (if any) and aborts the others it already started at that point.

Something like this would do I think. I didn’t test it though, it may be wrong :–)

let happy_eyeballs :
    delay_s:float -> tries:(unit -> 'a option) list -> discard:('a -> unit) ->
    'a option
=
fun ~delay_s ~tries ~discard ->
  let either fst snd = match Option.join fst with
  | None -> Option.join (Fiber.join snd)
  | Some _ as v ->
      Fiber.abort snd; Option.iter discard (Option.join (Fiber.join snd)); v
  in
  let rec loop = function
  | [] -> None
  | t :: ts ->
      let t = Fiber.spawn t in
      let ts = Fiber.spawn (fun () -> Funix.sleep_s delay_s; loop ts) in
      match Fiber.first t ts with
      | Either.Left t -> either t ts
      | Either.Right ts -> either ts t
  in
  loop tries

Note that you can’t use Fiber.either here, because it may drop a value without letting you discard it.

1 Like