|
16 | 16 |
|
17 | 17 | (* Extracted from https://github.com/pqwy/lru *)
|
18 | 18 |
|
19 |
| -module MakeUnsafe (H : Hashtbl.HashedType) = struct |
20 |
| - module HT = Hashtbl.Make (H) |
| 19 | +open Kcas |
| 20 | + |
| 21 | +module Make (H : Hashtbl.HashedType) = struct |
| 22 | + module HT = Kcas_data.Hashtbl |
21 | 23 |
|
22 | 24 | module Q = struct
|
23 | 25 | type 'a node = {
|
24 | 26 | value : 'a;
|
25 |
| - mutable next : 'a node option; |
26 |
| - mutable prev : 'a node option; |
| 27 | + next : 'a node option Loc.t; |
| 28 | + prev : 'a node option Loc.t; |
27 | 29 | }
|
28 | 30 |
|
29 |
| - type 'a t = { |
30 |
| - mutable first : 'a node option; |
31 |
| - mutable last : 'a node option; |
32 |
| - } |
| 31 | + type 'a t = { tail : 'a node option Loc.t; head : 'a node option Loc.t } |
33 | 32 |
|
34 |
| - let detach t n = |
35 |
| - let np = n.prev and nn = n.next in |
| 33 | + let detach ~xt t n = |
| 34 | + let np = Xt.get ~xt n.prev and nn = Xt.get ~xt n.next in |
36 | 35 | (match np with
|
37 |
| - | None -> t.first <- nn |
| 36 | + | None -> Xt.set ~xt t.tail nn |
38 | 37 | | Some x ->
|
39 |
| - x.next <- nn; |
40 |
| - n.prev <- None); |
| 38 | + Xt.set ~xt x.next nn; |
| 39 | + Xt.set ~xt n.prev None); |
41 | 40 | match nn with
|
42 |
| - | None -> t.last <- np |
| 41 | + | None -> Xt.set ~xt t.head np |
43 | 42 | | Some x ->
|
44 |
| - x.prev <- np; |
45 |
| - n.next <- None |
| 43 | + Xt.set ~xt x.prev np; |
| 44 | + Xt.set ~xt n.next None |
46 | 45 |
|
47 |
| - let append t n = |
| 46 | + let append ~xt t n = |
48 | 47 | let on = Some n in
|
49 |
| - match t.last with |
| 48 | + let hd = Xt.get ~xt t.head in |
| 49 | + match hd with |
50 | 50 | | Some x as l ->
|
51 |
| - x.next <- on; |
52 |
| - t.last <- on; |
53 |
| - n.prev <- l |
| 51 | + Xt.set ~xt x.next on; |
| 52 | + Xt.set ~xt t.head on; |
| 53 | + Xt.set ~xt n.prev l |
54 | 54 | | None ->
|
55 |
| - t.first <- on; |
56 |
| - t.last <- on |
57 |
| - |
58 |
| - let node x = { value = x; prev = None; next = None } |
59 |
| - let create () = { first = None; last = None } |
60 |
| - |
61 |
| - let iter t f = |
62 |
| - let rec aux f = function |
63 |
| - | Some n -> |
64 |
| - let next = n.next in |
65 |
| - f n.value; |
66 |
| - aux f next |
67 |
| - | _ -> () |
68 |
| - in |
69 |
| - aux f t.first |
| 55 | + Xt.set ~xt t.tail on; |
| 56 | + Xt.set ~xt t.head on |
70 | 57 |
|
71 |
| - let clear t = |
72 |
| - t.first <- None; |
73 |
| - t.last <- None |
| 58 | + let node x = { value = x; prev = Loc.make None; next = Loc.make None } |
| 59 | + let create () = { tail = Loc.make None; head = Loc.make None } |
| 60 | + |
| 61 | + let clear ~xt t = |
| 62 | + Xt.set ~xt t.tail None; |
| 63 | + Xt.set ~xt t.head None |
74 | 64 | end
|
75 | 65 |
|
76 |
| - type key = HT.key |
| 66 | + type key = H.t |
77 | 67 |
|
78 | 68 | type 'a t = {
|
79 |
| - ht : (key * 'a) Q.node HT.t; |
| 69 | + ht : (key, (key * 'a) Q.node) HT.t; |
80 | 70 | q : (key * 'a) Q.t;
|
81 |
| - mutable cap : cap; |
82 |
| - mutable w : int; |
| 71 | + cap : cap; |
| 72 | + w : int Loc.t; |
83 | 73 | }
|
84 | 74 |
|
85 | 75 | and cap = Uncapped | Capped of int
|
86 | 76 |
|
87 |
| - let weight t = t.w |
| 77 | + let weight ~xt t = Xt.get ~xt t.w |
88 | 78 |
|
89 | 79 | let create cap =
|
90 | 80 | let cap, ht_cap =
|
91 | 81 | if cap < 0 then (Uncapped, 65536) else (Capped cap, cap)
|
92 | 82 | in
|
93 |
| - { cap; w = 0; ht = HT.create ht_cap; q = Q.create () } |
| 83 | + { |
| 84 | + cap; |
| 85 | + w = Loc.make 0; |
| 86 | + ht = HT.create ~hashed_type:(module H) ~min_buckets:ht_cap (); |
| 87 | + q = Q.create (); |
| 88 | + } |
94 | 89 |
|
95 |
| - let drop t = |
96 |
| - match t.q.first with |
| 90 | + let drop ~xt t = |
| 91 | + let tl = Xt.get ~xt t.q.tail in |
| 92 | + match tl with |
97 | 93 | | None -> None
|
98 | 94 | | Some ({ Q.value = k, v; _ } as n) ->
|
99 |
| - t.w <- t.w - 1; |
100 |
| - HT.remove t.ht k; |
101 |
| - Q.detach t.q n; |
| 95 | + Xt.modify ~xt t.w (fun tw -> tw - 1); |
| 96 | + HT.Xt.remove ~xt t.ht k; |
| 97 | + Q.detach ~xt t.q n; |
102 | 98 | Some v
|
103 | 99 |
|
104 |
| - let remove t k = |
105 |
| - try |
106 |
| - let n = HT.find t.ht k in |
107 |
| - t.w <- t.w - 1; |
108 |
| - HT.remove t.ht k; |
109 |
| - Q.detach t.q n |
110 |
| - with Not_found -> () |
| 100 | + let remove ~xt t k = |
| 101 | + match HT.Xt.find_opt ~xt t.ht k with |
| 102 | + | None -> () |
| 103 | + | Some n -> |
| 104 | + Xt.modify ~xt t.w (fun tw -> tw - 1); |
| 105 | + HT.Xt.remove ~xt t.ht k; |
| 106 | + Q.detach ~xt t.q n |
111 | 107 |
|
112 | 108 | let add t k v =
|
113 |
| - let add t k v = |
114 |
| - remove t k; |
115 |
| - let n = Q.node (k, v) in |
116 |
| - t.w <- t.w + 1; |
117 |
| - HT.add t.ht k n; |
118 |
| - Q.append t.q n |
| 109 | + let tx ~xt = |
| 110 | + let add t k v = |
| 111 | + remove ~xt t k; |
| 112 | + let n = Q.node (k, v) in |
| 113 | + Xt.modify ~xt t.w (fun tw -> tw + 1); |
| 114 | + HT.Xt.replace ~xt t.ht k n; |
| 115 | + Q.append ~xt t.q n |
| 116 | + in |
| 117 | + match t.cap with |
| 118 | + | Capped c when c = 0 -> () |
| 119 | + | Uncapped -> add t k v |
| 120 | + | Capped c -> |
| 121 | + add t k v; |
| 122 | + if weight ~xt t > c then |
| 123 | + let _ = drop ~xt t in |
| 124 | + () |
119 | 125 | in
|
120 |
| - match t.cap with |
121 |
| - | Capped c when c = 0 -> () |
122 |
| - | Uncapped -> add t k v |
123 |
| - | Capped c -> |
124 |
| - add t k v; |
125 |
| - if weight t > c then |
126 |
| - let _ = drop t in |
127 |
| - () |
128 |
| - |
129 |
| - let promote t k = |
130 |
| - try |
131 |
| - let n = HT.find t.ht k in |
132 |
| - Q.( |
133 |
| - detach t.q n; |
134 |
| - append t.q n) |
135 |
| - with Not_found -> () |
136 |
| - |
137 |
| - let find_opt t k = |
138 |
| - match HT.find_opt t.ht k with |
139 |
| - | Some v -> |
140 |
| - promote t k; |
141 |
| - Some (snd v.value) |
142 |
| - | None -> None |
143 |
| - |
144 |
| - let mem t k = |
145 |
| - match HT.mem t.ht k with |
146 |
| - | false -> false |
147 |
| - | true -> |
148 |
| - promote t k; |
149 |
| - true |
150 |
| - |
151 |
| - let iter t f = Q.iter t.q (fun (k, v) -> f k v) |
152 |
| - |
153 |
| - let clear t = |
154 |
| - t.w <- 0; |
155 |
| - HT.clear t.ht; |
156 |
| - Q.clear t.q |
157 |
| -end |
158 |
| - |
159 |
| -(** Safe but might be incredibly slow. *) |
160 |
| -module Make (H : Hashtbl.HashedType) = struct |
161 |
| - module Unsafe = MakeUnsafe (H) |
162 |
| - |
163 |
| - type 'a t = { lock : Eio.Mutex.t; data : 'a Unsafe.t } |
164 |
| - |
165 |
| - let create cap = |
166 |
| - let lock = Eio.Mutex.create () in |
167 |
| - let data = Unsafe.create cap in |
168 |
| - { lock; data } |
169 |
| - |
170 |
| - let add { lock; data } k v = |
171 |
| - Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.add data k v |
| 126 | + Xt.commit { tx } |
172 | 127 |
|
173 |
| - let find_opt { lock; data } k = |
174 |
| - Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.find_opt data k |
| 128 | + let drop t = Xt.commit { tx = drop t } |
175 | 129 |
|
176 |
| - let find t k = match find_opt t k with Some v -> v | None -> raise Not_found |
| 130 | + let promote ~xt t n = |
| 131 | + Q.detach ~xt t.q n; |
| 132 | + Q.append ~xt t.q n |
177 | 133 |
|
178 |
| - let mem { lock; data } k = |
179 |
| - Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.mem data k |
| 134 | + let find t k = |
| 135 | + let tx ~xt = |
| 136 | + match HT.Xt.find_opt ~xt t.ht k with |
| 137 | + | Some v -> |
| 138 | + promote ~xt t v; |
| 139 | + snd v.value |
| 140 | + | None -> |
| 141 | + raise Not_found |
| 142 | + in |
| 143 | + Xt.commit { tx } |
180 | 144 |
|
181 |
| - let iter { lock; data } f = |
182 |
| - Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.iter data f |
| 145 | + let mem t k = |
| 146 | + let tx ~xt = |
| 147 | + match HT.Xt.find_opt ~xt t.ht k with |
| 148 | + | None -> false |
| 149 | + | Some v -> |
| 150 | + promote ~xt t v; |
| 151 | + true |
| 152 | + in |
| 153 | + Xt.commit { tx } |
183 | 154 |
|
184 |
| - let clear { lock; data } = |
185 |
| - Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.clear data |
| 155 | + let clear t = |
| 156 | + let tx ~xt = |
| 157 | + Xt.set ~xt t.w 0; |
| 158 | + HT.Xt.clear ~xt t.ht; |
| 159 | + Q.clear ~xt t.q |
| 160 | + in |
| 161 | + Xt.commit { tx } |
186 | 162 |
|
187 |
| - let drop { lock; data } = |
188 |
| - Eio.Mutex.use_rw ~protect:true lock @@ fun () -> Unsafe.drop data |
189 | 163 | end
|
0 commit comments