Skip to content

Commit 75644be

Browse files
committed
Add Picos_htbl.remove_exn to atomically find and remove a binding
1 parent 7cf277e commit 75644be

File tree

2 files changed

+25
-14
lines changed

2 files changed

+25
-14
lines changed

lib/picos_htbl/picos_htbl.ml

Lines changed: 21 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -254,7 +254,7 @@ let[@inline never] try_resize t r new_capacity =
254254
true
255255
end
256256

257-
let rec adjust_estimated_size t r mask delta =
257+
let rec adjust_estimated_size t r mask delta result =
258258
let i = Multicore_magic.instantaneous_domain_index () in
259259
let n = Array.length r.non_linearizable_size in
260260
if i < n then begin
@@ -273,7 +273,7 @@ let rec adjust_estimated_size t r mask delta =
273273
&& estimated_size + estimated_size + estimated_size < capacity
274274
then try_resize t r (capacity lsr 1) |> ignore
275275
end;
276-
true
276+
result
277277
end
278278
else
279279
let new_cs =
@@ -289,7 +289,7 @@ let rec adjust_estimated_size t r mask delta =
289289
|> Multicore_magic.copy_as_padded
290290
in
291291
let r = if Atomic.compare_and_set t r new_r then new_r else Atomic.get t in
292-
adjust_estimated_size t r mask delta
292+
adjust_estimated_size t r mask delta result
293293

294294
(* *)
295295

@@ -341,14 +341,14 @@ let rec try_add t key value backoff =
341341
| B Nil ->
342342
let after = Cons { key; value; rest = Nil } in
343343
if Atomic.compare_and_set b (B Nil) (B after) then
344-
adjust_estimated_size t r mask 1
344+
adjust_estimated_size t r mask 1 true
345345
else try_add t key value (Backoff.once backoff)
346346
| B (Cons _ as before) ->
347347
if assoc_node r.equal key before != Nil then false
348348
else
349349
let after = Cons { key; value; rest = before } in
350350
if Atomic.compare_and_set b (B before) (B after) then
351-
adjust_estimated_size t r mask 1
351+
adjust_estimated_size t r mask 1 true
352352
else try_add t key value (Backoff.once backoff)
353353
| B (Resize _) -> try_add t key value Backoff.default
354354

@@ -361,32 +361,39 @@ let[@tail_mod_cons] rec dissoc t key = function
361361
| Cons r ->
362362
if t key r.key then r.rest else Cons { r with rest = dissoc t key r.rest }
363363

364-
let rec try_remove t key backoff =
364+
let rec remove_node t key backoff =
365365
let r = get t in
366366
let h = r.hash key in
367367
let mask = Array.length r.buckets - 1 in
368368
let i = h land mask in
369369
let b = Array.unsafe_get r.buckets i in
370370
match Atomic.get b with
371-
| B Nil -> false
371+
| B Nil -> Nil
372372
| B (Cons cons_r as before) -> begin
373373
if r.equal cons_r.key key then
374374
if Atomic.compare_and_set b (B before) (B cons_r.rest) then
375-
adjust_estimated_size t r mask (-1)
376-
else try_remove t key (Backoff.once backoff)
375+
adjust_estimated_size t r mask (-1) before
376+
else remove_node t key (Backoff.once backoff)
377377
else
378378
match dissoc r.equal key cons_r.rest with
379379
| (Nil | Cons _) as rest ->
380380
if
381381
Atomic.compare_and_set b (B before)
382382
(B (Cons { cons_r with rest }))
383-
then adjust_estimated_size t r mask (-1)
384-
else try_remove t key (Backoff.once backoff)
385-
| exception Not_found -> false
383+
then
384+
assoc_node r.equal key cons_r.rest
385+
|> adjust_estimated_size t r mask (-1)
386+
else remove_node t key (Backoff.once backoff)
387+
| exception Not_found -> Nil
386388
end
387-
| B (Resize _) -> try_remove t key Backoff.default
389+
| B (Resize _) -> remove_node t key Backoff.default
390+
391+
let try_remove t key = remove_node t key Backoff.default != Nil
388392

389-
let try_remove t key = try_remove t key Backoff.default
393+
let remove_exn t key =
394+
match remove_node t key Backoff.default with
395+
| Nil -> raise_notrace Not_found
396+
| Cons r -> r.value
390397

391398
(* *)
392399

lib/picos_htbl/picos_htbl.mli

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -37,6 +37,10 @@ val try_remove : ('k, 'v) t -> 'k -> bool
3737
[htbl]. Returns [true] on success and [false] in case the hash table did
3838
not contain a binding for [key]. *)
3939

40+
val remove_exn : ('k, 'v) t -> 'k -> 'v
41+
(** [remove_exn htbl key] tries to remove a binding of [key] from the hash table
42+
[htbl] and return it or raise {!Not_found} if no such binding exists. *)
43+
4044
val to_seq : ('k, 'v) t -> ('k * 'v) Seq.t
4145
(** [to_seq htbl] takes a snapshot of the bindings in the hash table and returns
4246
them as an association sequence.

0 commit comments

Comments
 (0)