mirror of
https://github.com/ocaml-tracing/ocaml-opentelemetry.git
synced 2026-03-08 20:07:55 -04:00
fix: mutex usage and inline bugs
This commit is contained in:
parent
507bf25dcf
commit
3fbac32822
3 changed files with 43 additions and 29 deletions
|
|
@ -7,6 +7,19 @@ type 'a t = {
|
||||||
|
|
||||||
exception Closed
|
exception Closed
|
||||||
|
|
||||||
|
(* Mutex.protect was added in OCaml 5.1, but we want support back to 4.08 *)
|
||||||
|
(* cannot inline, otherwise flambda might move code around. (as per Stdlib) *)
|
||||||
|
let[@inline never] protect m f =
|
||||||
|
Mutex.lock m;
|
||||||
|
match f () with
|
||||||
|
| x ->
|
||||||
|
Mutex.unlock m;
|
||||||
|
x
|
||||||
|
| exception e ->
|
||||||
|
(* NOTE: [unlock] does not poll for asynchronous exceptions *)
|
||||||
|
Mutex.unlock m;
|
||||||
|
Printexc.raise_with_backtrace e (Printexc.get_raw_backtrace ())
|
||||||
|
|
||||||
let create () : _ t =
|
let create () : _ t =
|
||||||
{
|
{
|
||||||
mutex = Mutex.create ();
|
mutex = Mutex.create ();
|
||||||
|
|
@ -16,54 +29,42 @@ let create () : _ t =
|
||||||
}
|
}
|
||||||
|
|
||||||
let close (self : _ t) =
|
let close (self : _ t) =
|
||||||
Mutex.lock self.mutex;
|
protect self.mutex @@ fun () ->
|
||||||
if not self.closed then (
|
if not self.closed then (
|
||||||
self.closed <- true;
|
self.closed <- true;
|
||||||
Condition.broadcast self.cond (* awake waiters so they fail *)
|
Condition.broadcast self.cond (* awake waiters so they fail *)
|
||||||
);
|
)
|
||||||
Mutex.unlock self.mutex
|
|
||||||
|
|
||||||
let push (self : _ t) x : unit =
|
let push (self : _ t) x : unit =
|
||||||
Mutex.lock self.mutex;
|
protect self.mutex @@ fun () ->
|
||||||
if self.closed then (
|
if self.closed then
|
||||||
Mutex.unlock self.mutex;
|
|
||||||
raise Closed
|
raise Closed
|
||||||
) else (
|
else (
|
||||||
Queue.push x self.q;
|
Queue.push x self.q;
|
||||||
Condition.signal self.cond;
|
Condition.signal self.cond
|
||||||
Mutex.unlock self.mutex
|
|
||||||
)
|
)
|
||||||
|
|
||||||
let pop (self : 'a t) : 'a =
|
let pop (self : 'a t) : 'a =
|
||||||
Mutex.lock self.mutex;
|
|
||||||
let rec loop () =
|
let rec loop () =
|
||||||
if self.closed then (
|
if self.closed then
|
||||||
Mutex.unlock self.mutex;
|
|
||||||
raise Closed
|
raise Closed
|
||||||
) else if Queue.is_empty self.q then (
|
else if Queue.is_empty self.q then (
|
||||||
Condition.wait self.cond self.mutex;
|
Condition.wait self.cond self.mutex;
|
||||||
(loop [@tailcall]) ()
|
(loop [@tailcall]) ()
|
||||||
) else (
|
) else (
|
||||||
let x = Queue.pop self.q in
|
let x = Queue.pop self.q in
|
||||||
Mutex.unlock self.mutex;
|
|
||||||
x
|
x
|
||||||
)
|
)
|
||||||
in
|
in
|
||||||
loop ()
|
protect self.mutex loop
|
||||||
|
|
||||||
let pop_all (self : 'a t) into : unit =
|
let pop_all (self : 'a t) into : unit =
|
||||||
Mutex.lock self.mutex;
|
|
||||||
let rec loop () =
|
let rec loop () =
|
||||||
if Queue.is_empty self.q then (
|
if Queue.is_empty self.q then (
|
||||||
if self.closed then (
|
if self.closed then raise Closed;
|
||||||
Mutex.unlock self.mutex;
|
|
||||||
raise Closed
|
|
||||||
);
|
|
||||||
Condition.wait self.cond self.mutex;
|
Condition.wait self.cond self.mutex;
|
||||||
(loop [@tailcall]) ()
|
(loop [@tailcall]) ()
|
||||||
) else (
|
) else
|
||||||
Queue.transfer self.q into;
|
Queue.transfer self.q into
|
||||||
Mutex.unlock self.mutex
|
|
||||||
)
|
|
||||||
in
|
in
|
||||||
loop ()
|
protect self.mutex loop
|
||||||
|
|
|
||||||
|
|
@ -9,11 +9,18 @@ type 'a t = {
|
||||||
mutex: Mutex.t;
|
mutex: Mutex.t;
|
||||||
}
|
}
|
||||||
|
|
||||||
(* Mutex.protect was added in OCaml 5.1, but we want support back to 4.08.
|
(* Mutex.protect was added in OCaml 5.1, but we want support back to 4.08 *)
|
||||||
cannot inline, otherwise flambda might move code around. (as per Stdlib) *)
|
(* cannot inline, otherwise flambda might move code around. (as per Stdlib) *)
|
||||||
let[@inline never] protect_mutex m f =
|
let[@inline never] protect_mutex m f =
|
||||||
Mutex.lock m;
|
Mutex.lock m;
|
||||||
Fun.protect f ~finally:(fun () -> Mutex.unlock m)
|
match f () with
|
||||||
|
| x ->
|
||||||
|
Mutex.unlock m;
|
||||||
|
x
|
||||||
|
| exception e ->
|
||||||
|
(* NOTE: [unlock] does not poll for asynchronous exceptions *)
|
||||||
|
Mutex.unlock m;
|
||||||
|
Printexc.raise_with_backtrace e (Printexc.get_raw_backtrace ())
|
||||||
|
|
||||||
let default_high_watermark batch_size =
|
let default_high_watermark batch_size =
|
||||||
if batch_size = 1 then
|
if batch_size = 1 then
|
||||||
|
|
|
||||||
|
|
@ -8,4 +8,10 @@ let set_mutex ~lock ~unlock : unit =
|
||||||
|
|
||||||
let[@inline] with_lock f =
|
let[@inline] with_lock f =
|
||||||
!lock_ ();
|
!lock_ ();
|
||||||
Fun.protect ~finally:!unlock_ f
|
match f () with
|
||||||
|
| x ->
|
||||||
|
!unlock_ ();
|
||||||
|
x
|
||||||
|
| exception e ->
|
||||||
|
!unlock_ ();
|
||||||
|
Printexc.raise_with_backtrace e (Printexc.get_raw_backtrace ())
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue