Skip to content

Commit dd93e95

Browse files
committed
Add optional capacity argument to Queue.create and Stack.create
1 parent bb2571c commit dd93e95

12 files changed

+366
-95
lines changed

src/kcas_data/elems.ml

+11
Original file line numberDiff line numberDiff line change
@@ -41,3 +41,14 @@ let rev_prepend_to_seq t tl =
4141
| `Reversed t' -> t'
4242
in
4343
prepend_to_seq t tl ()
44+
45+
let rec of_list_rev tl length = function
46+
| [] -> tl
47+
| x :: xs ->
48+
let length = length + 1 in
49+
of_list_rev { value = x; tl; length } length xs
50+
51+
let of_list_rev = function
52+
| [] -> empty
53+
| x :: xs -> of_list_rev (singleton x) 1 xs
54+
[@@inline]

src/kcas_data/elems.mli

+1
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,4 @@ val prepend_to_seq : 'a t -> 'a Seq.t -> 'a Seq.t
1818
val to_seq : 'a t -> 'a Seq.t
1919
val of_seq_rev : 'a Seq.t -> 'a t
2020
val rev_prepend_to_seq : 'a t -> 'a Seq.t -> 'a Seq.t
21+
val of_list_rev : 'a list -> 'a t

src/kcas_data/list_with_capacity.ml

+121
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,121 @@
1+
open Kcas
2+
3+
type 'a t = { capacity : int; length : int; list : 'a list; limit : int }
4+
5+
let empty_unlimited =
6+
{ capacity = Int.max_int; length = 0; list = []; limit = Int.max_int }
7+
8+
let make_empty ~capacity =
9+
if capacity = Int.max_int then empty_unlimited
10+
else { capacity; length = 0; list = []; limit = capacity }
11+
[@@inline]
12+
13+
let make ~capacity ~length ~list ~limit = { capacity; length; list; limit }
14+
[@@inline]
15+
16+
let to_rev_elems t = Elems.of_list_rev t.list [@@inline]
17+
let is_empty t = t.length = 0 [@@inline]
18+
let length t = t.length [@@inline]
19+
let capacity t = t.capacity [@@inline]
20+
let limit t = t.limit [@@inline]
21+
let list t = t.list [@@inline]
22+
23+
let tl_safe = function
24+
| { list = []; _ } as t -> t
25+
| { capacity; length; list = _ :: list; _ } as t ->
26+
let limit = if capacity = Int.max_int then capacity else t.limit in
27+
{ capacity; length = length - 1; list; limit }
28+
[@@inline]
29+
30+
let tl_or_retry = function
31+
| { list = []; _ } -> Retry.later ()
32+
| { capacity; length; list = _ :: list; _ } as t ->
33+
let limit = if capacity = Int.max_int then capacity else t.limit in
34+
{ capacity; length = length - 1; list; limit }
35+
[@@inline]
36+
37+
let hd_opt t = match t.list with [] -> None | x :: _ -> Some x [@@inline]
38+
39+
let hd_or_retry t = match t.list with [] -> Retry.later () | x :: _ -> x
40+
[@@inline]
41+
42+
let hd_unsafe t = List.hd t.list [@@inline]
43+
44+
let cons_safe x ({ capacity; _ } as t) =
45+
if capacity = Int.max_int then
46+
let { length; list; _ } = t in
47+
{ capacity; length = length + 1; list = x :: list; limit = capacity }
48+
else
49+
let { length; limit; _ } = t in
50+
if length < limit then
51+
let { list; _ } = t in
52+
{ capacity; length = length + 1; list = x :: list; limit }
53+
else t
54+
[@@inline]
55+
56+
let cons_or_retry x ({ capacity; _ } as t) =
57+
if capacity = Int.max_int then
58+
let { length; list; _ } = t in
59+
{ capacity; length = length + 1; list = x :: list; limit = capacity }
60+
else
61+
let { length; limit; _ } = t in
62+
if length < limit then
63+
let { list; _ } = t in
64+
{ capacity; length = length + 1; list = x :: list; limit }
65+
else Retry.later ()
66+
[@@inline]
67+
68+
let move ({ capacity; _ } as t) =
69+
if capacity = Int.max_int then empty_unlimited
70+
else
71+
let { length; _ } = t in
72+
if length = 0 then t
73+
else
74+
let { limit; _ } = t in
75+
{ capacity; length = 0; list = []; limit = limit - length }
76+
[@@inline]
77+
78+
let move_last ({ capacity; _ } as t) =
79+
if capacity = Int.max_int then empty_unlimited
80+
else
81+
let { length; _ } = t in
82+
let limit = capacity - length in
83+
if length = 0 && t.limit = limit then t
84+
else { capacity; length = 0; list = []; limit }
85+
86+
let clear ({ capacity; _ } as t) =
87+
if capacity = Int.max_int then empty_unlimited
88+
else if t.length = 0 && t.limit = capacity then t
89+
else make_empty ~capacity
90+
[@@inline]
91+
92+
let rec prepend_to_seq xs tl =
93+
match xs with
94+
| [] -> tl
95+
| x :: xs -> fun () -> Seq.Cons (x, prepend_to_seq xs tl)
96+
97+
let to_seq { list; _ } = prepend_to_seq list Seq.empty
98+
99+
let rev_prepend_to_seq { length; list; _ } tl =
100+
if length <= 1 then prepend_to_seq list tl
101+
else
102+
let t = ref (`Original list) in
103+
fun () ->
104+
let t =
105+
match !t with
106+
| `Original t' ->
107+
(* This is domain safe as the result is always equivalent. *)
108+
let t' = List.rev t' in
109+
t := `Reversed t';
110+
t'
111+
| `Reversed t' -> t'
112+
in
113+
prepend_to_seq t tl ()
114+
115+
let of_list ?(capacity = Int.max_int) list =
116+
let length = List.length list in
117+
let limit = Int.min 0 (capacity - length) in
118+
{ capacity; length; list; limit }
119+
120+
let of_seq_rev ?capacity xs =
121+
of_list ?capacity (Seq.fold_left (fun xs x -> x :: xs) [] xs)

src/kcas_data/list_with_capacity.mli

+24
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
type !'a t
2+
3+
val empty_unlimited : 'a t
4+
val make_empty : capacity:int -> 'a t
5+
val make : capacity:int -> length:int -> list:'a list -> limit:int -> 'a t
6+
val is_empty : 'a t -> bool
7+
val length : 'a t -> int
8+
val capacity : 'a t -> int
9+
val limit : 'a t -> int
10+
val list : 'a t -> 'a list
11+
val cons_safe : 'a -> 'a t -> 'a t
12+
val cons_or_retry : 'a -> 'a t -> 'a t
13+
val move : 'a t -> 'a t
14+
val move_last : 'a t -> 'a t
15+
val clear : 'a t -> 'a t
16+
val to_rev_elems : 'a t -> 'a Elems.t
17+
val to_seq : 'a t -> 'a Seq.t
18+
val rev_prepend_to_seq : 'a t -> 'a Seq.t -> 'a Seq.t
19+
val of_seq_rev : ?capacity:int -> 'a Seq.t -> 'a t
20+
val tl_safe : 'a t -> 'a t
21+
val tl_or_retry : 'a t -> 'a t
22+
val hd_opt : 'a t -> 'a option
23+
val hd_or_retry : 'a t -> 'a
24+
val hd_unsafe : 'a t -> 'a

0 commit comments

Comments
 (0)