mirror of
https://github.com/zap-proto/ocaml-rpc.git
synced 2026-10-30 15:04:28 +00:00
This switches capnp-rpc from Lwt to Eio. One particularly nice side effect of this is that `Service.return_lwt` has gone, as there is no distinction now between concurrent and non-concurrent service methods.
55 lines
1.7 KiB
OCaml
55 lines
1.7 KiB
OCaml
module M = Map.Make(Int)
|
|
|
|
module Log = Capnp_rpc_proto.Debug.Log
|
|
|
|
(* A map from thread IDs to (n, q) pairs.
|
|
[q] is a queue of callbacks waiting to be run in the thread
|
|
and [n] is the number of loops consuming [q] (typically 1). *)
|
|
let handlers : (int * (unit -> unit) Eio.Stream.t) M.t Atomic.t = Atomic.make M.empty
|
|
|
|
(* [add_handler id] increments the counter for thread [id] and returns the queue.
|
|
If there isn't one yet, it creates a new one. *)
|
|
let rec add_handler id =
|
|
let old = Atomic.get handlers in
|
|
let handler =
|
|
match M.find_opt id old with
|
|
| None -> (1, Eio.Stream.create max_int)
|
|
| Some (n, q) -> (n + 1, q)
|
|
in
|
|
let next = M.add id handler old in
|
|
if Atomic.compare_and_set handlers old next then snd handler
|
|
else add_handler id
|
|
|
|
let rec remove_handler id =
|
|
let old = Atomic.get handlers in
|
|
let n, q = M.find id old in
|
|
let next =
|
|
if n > 1 then M.add id (n - 1, q) old
|
|
else M.remove id old
|
|
in
|
|
if not (Atomic.compare_and_set handlers old next) then remove_handler id
|
|
|
|
let run () =
|
|
let id = Thread.(id (self ())) in
|
|
let q = add_handler id in
|
|
try
|
|
while true do
|
|
let fn = Eio.Stream.take q in
|
|
try
|
|
fn ()
|
|
with ex ->
|
|
let bt = Printexc.get_raw_backtrace () in
|
|
Eio.Fiber.check ();
|
|
Log.warn (fun f -> f "Uncaught exception handling ref-leak: %a" Fmt.exn_backtrace (ex, bt))
|
|
done
|
|
with ex ->
|
|
remove_handler id;
|
|
raise ex
|
|
|
|
let ref_leak_detected thread fn =
|
|
match M.find_opt thread (Atomic.get handlers) with
|
|
| Some (_, q) -> Eio.Stream.add q fn
|
|
| None ->
|
|
Capnp_rpc_proto.Debug.Log.debug
|
|
(fun f -> f "Leak detected, but no leak reporter is running so ignoring")
|