package trace

  1. Overview
  2. Docs

Source file rpool.ml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
open struct
  module A = Trace_core.Internal_.Atomic_
end

module List_with_len = struct
  type +'a t =
    | Nil
    | Cons of int * 'a * 'a t

  let empty : _ t = Nil

  let[@inline] len = function
    | Nil -> 0
    | Cons (i, _, _) -> i

  let[@inline] cons x self = Cons (len self + 1, x, self)
end

type 'a t = {
  max_size: int;
  create: unit -> 'a;
  clear: 'a -> unit;
  cached: 'a List_with_len.t A.t;
}

let create ~max_size ~create ~clear () : _ t =
  { max_size; create; clear; cached = A.make List_with_len.empty }

let alloc (type a) (self : a t) : a =
  let module M = struct
    exception Found of a
  end in
  try
    while
      match A.get self.cached with
      | Nil -> false
      | Cons (_, x, tl) as old ->
        if A.compare_and_set self.cached old tl then
          raise_notrace (M.Found x)
        else
          true
    do
      ()
    done;
    self.create ()
  with M.Found x -> x

let recycle (self : 'a t) (x : 'a) : unit =
  self.clear x;
  while
    match A.get self.cached with
    | Cons (i, _, _) when i >= self.max_size -> false (* drop buf *)
    | old -> not (A.compare_and_set self.cached old (List_with_len.cons x old))
  do
    ()
  done

let with_ (self : 'a t) f =
  let x = alloc self in
  try
    let res = f x in
    recycle self x;
    res
  with e ->
    let bt = Printexc.get_raw_backtrace () in
    recycle self x;
    Printexc.raise_with_backtrace e bt
OCaml

Innovation. Community. Security.