apologies if this is a common question or indeed impossible,
I am using some library code that runs a big computation as an 'a Lwt.t promise, the library code calls out to a user-defined callback function : int → int → unit (I’ve simplified here but key point is that it returns unit), I want to pause that same 'a Lwt.t when that callback is invoked and for the Ui to unpause it.
Here is a simplified example (I know that using read_line blocks everything but it almost illustrates what I am after): :
(* this Worker module would be library code, ie I cant edit it *)
(* but I can implement my own pauser.stop function *)
module Worker = struct
type pauser = {
stop: int -> int -> unit;
}
let long_running_lwt n pauser =
let rec aux i () =
match i with
| 0 -> Lwt.return_unit
| _ ->
(* the library calls out to the callback and then does some work *)
let _ = pauser.stop i n in
(Lwt_unix.sleep 0.2) >>=
aux (i-1)
in
aux n
end
(* this Ui module is my code, am free to write whatever *)
module Ui = struct
let ui_thread n =
let rec aux i () =
match i with
| 0 -> Lwt.return_unit
| _ ->
Lwt_io.printlf "ui thread doing stuff %d/%d" (n-i+1) n >>=
(fun _ -> Lwt_io.(flush stdout)) >>=
(fun _ -> Lwt_unix.sleep 1.1) >>=
aux (i-1)
in
aux n
end
(* likewise I'm free to write my own pauser callback *)
let p : Worker.pauser = {
stop=fun i n ->
print_endline @@ Printf.sprintf "hello from pauser %d/%d\n" (n-i+1) n;
let ch = read_line () in (* this line blocks everything, want to only block worker thread until Ui unpauses*)
print_endline @@ Printf.sprintf "echo: %s" ch;
}
let () =
let w = Worker.long_running_lwt 5 p () in
let ui = Ui.ui_thread 10 () in
Lwt_main.run @@ (Lwt.join [w; ui])