module type LOOP = sig
type acc
val main : acc -> acc Lwt.t
val catch : acc -> Exception.t -> unit Lwt.t
end
module Make (Loop : LOOP) : sig
val run : ?cancel_condition:'a Lwt_condition.t -> Loop.acc -> unit Lwt.t
end = struct
let catch acc exn =
match exn with
| Lwt.Canceled -> Lwt.return_unit
| exn -> Loop.catch acc (Exception.wrap exn)
let rec loop acc =
Lwt.try_bind
(fun () ->
let%lwt () = Lwt.pause () in
Loop.main acc)
loop
(catch acc)
let run ?cancel_condition acc =
let (waiter, wakener) = Lwt.task () in
let thread =
let%lwt ret = waiter in
loop ret
in
begin
match cancel_condition with
| None -> ()
| Some condition ->
Lwt.async (fun () ->
Lwt.pick
[
(try%lwt thread with Lwt.Canceled -> Lwt.return_unit);
(let%lwt _ = Lwt_condition.wait condition in
Lwt.return_unit);
])
end;
Lwt.wakeup wakener acc;
thread
end