···11+(** Worker rpc *)
22+33+(** Functions to facilitate RPC calls to web workers. *)
44+55+module Worker = Brr_webworkers.Worker
66+open Brr_io
77+open Js_top_worker_rpc
88+99+(** The assumption made in this module is that RPCs are answered in the order
1010+ they are made. *)
1111+1212+type context =
1313+ { worker : Worker.t
1414+ ; timeout : int
1515+ ; timeout_fn : unit -> unit
1616+ ; waiting : ((Rpc.response, exn) Result.t Lwt_mvar.t * int) Queue.t
1717+ }
1818+1919+exception Timeout
2020+2121+let demux context msg =
2222+ Lwt.async (fun () ->
2323+ match Queue.take_opt context.waiting with
2424+ | None ->
2525+ Lwt.return ()
2626+ | Some (mv, outstanding_execution) ->
2727+ Brr.G.stop_timer outstanding_execution;
2828+ let msg : string = Message.Ev.data (Brr.Ev.as_type msg) in
2929+ Lwt_mvar.put mv (Ok (Marshal.from_string msg 0)))
3030+3131+let start worker timeout timeout_fn =
3232+ let context = { worker; timeout; timeout_fn; waiting = Queue.create () } in
3333+ let () =
3434+ Brr.Ev.listen Message.Ev.message (demux context) (Worker.as_target worker)
3535+ in
3636+ context
3737+3838+let rpc : context -> Rpc.call -> Rpc.response Lwt.t =
3939+ fun context call ->
4040+ let open Lwt in
4141+ let jv = Marshal.to_bytes call [] in
4242+ let mv = Lwt_mvar.create_empty () in
4343+ let outstanding_execution =
4444+ Brr.G.set_timeout ~ms:1000000 (fun () ->
4545+ Lwt.async (fun () -> Lwt_mvar.put mv (Error Timeout));
4646+ context.timeout_fn ())
4747+ in
4848+ Queue.push (mv, outstanding_execution) context.waiting;
4949+ Worker.post context.worker jv;
5050+ Lwt_mvar.take mv >>= fun r ->
5151+ match r with
5252+ | Ok jv ->
5353+ let response = jv in
5454+ Lwt.return response
5555+ | Error exn ->
5656+ Lwt.fail exn
+26
idl/worker_rpc.mli
···11+(* Worker_rpc *)
22+33+(** Functions to facilitate RPC calls to web workers.
44+55+ The assumption made in this module is that RPCs are answered in the order
66+ they are made. *)
77+88+(** Represents the channel used to communicate with the worker *)
99+type context
1010+1111+(** When RPC calls take too long, the Lwt promise is set to failed state with
1212+ this exception. *)
1313+exception Timeout
1414+1515+val start : Brr_webworkers.Worker.t -> int -> (unit -> unit) -> context
1616+(** [start worker timeout timeout_fn] initialises communications with a web
1717+ worker. [timeout] is the number of seconds to wait for a response from any
1818+ RPC before raising an error, and [timeout_fn] is called when a timeout
1919+ occurs. *)
2020+2121+open Js_top_worker_rpc
2222+2323+val rpc : context -> Rpc.call -> Rpc.response Lwt.t
2424+(** [rpc context call] returns a promise containing the result from the worker.
2525+ If we wait longer than the timeout specified in [context] for a response,
2626+ the Lwt promise will fail with exception {!Timeout}. *)