Skip to content

Commit cc4ac0d

Browse files
committed
Expose Dllist type to allow matchable cursors
Being able to freely point to locations in a double-linked list allows more uses for a double-linked list.
1 parent 97e6f09 commit cc4ac0d

File tree

5 files changed

+50
-4
lines changed

5 files changed

+50
-4
lines changed

README.md

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1028,7 +1028,12 @@ We can then test that the cache works as expected:
10281028
# let a_cache : (int, string) cache = cache 2
10291029
val a_cache : (int, string) cache =
10301030
{space = Kcas.Loc.Loc {Kcas.Loc.state = <poly>; id = <poly>};
1031-
table = <abstr>; order = <abstr>}
1031+
table = <abstr>;
1032+
order =
1033+
Kcas_data.Dllist.List
1034+
{Kcas_data.Dllist.lhs =
1035+
Kcas.Loc.Loc {Kcas.Loc.state = <poly>; id = <poly>};
1036+
rhs = Kcas.Loc.Loc {Kcas.Loc.state = <poly>; id = <poly>}}}
10321037
10331038
# Xt.commit { tx = set_blocking a_cache 101 "basics" }
10341039
- : unit = ()

src/kcas_data/dllist.ml

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ let create_node_with ~lhs ~rhs value =
7070
Node { lhs = Loc.make (At lhs); rhs = Loc.make (At rhs); value }
7171

7272
module Xt = struct
73+
let get_l ~xt (At at) = Xt.get ~xt (lhs_of at)
74+
let get_r ~xt (At at) = Xt.get ~xt (rhs_of at)
75+
7376
let remove ~xt node =
7477
let (At rhs) = Xt.exchange ~xt (rhs_of node) (At node) in
7578
if At rhs != At node then begin
@@ -210,6 +213,8 @@ module Xt = struct
210213
let to_nodes_r ~xt list = to_list_as_r ~xt Fun.id list
211214
end
212215

216+
let get_l (At at) = Loc.get (lhs_of at)
217+
let get_r (At at) = Loc.get (rhs_of at)
213218
let remove node = Kcas.Xt.commit { tx = Xt.remove node }
214219
let is_empty list = Loc.get (lhs_of list) == At list
215220

src/kcas_data/dllist.mli

Lines changed: 21 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,10 +33,27 @@ open Kcas
3333

3434
(** {1 Common interface} *)
3535

36-
type !'a t
36+
(** Tagged GADT for doubly-linked lists. *)
37+
type ('a, _) tdt =
38+
| List : {
39+
lhs : 'a cursor Loc.t;
40+
rhs : 'a cursor Loc.t;
41+
}
42+
-> ('a, [> `List ]) tdt
43+
| Node : {
44+
lhs : 'a cursor Loc.t;
45+
rhs : 'a cursor Loc.t;
46+
value : 'a;
47+
}
48+
-> ('a, [> `Node ]) tdt
49+
50+
(** Refers to either a {!Node} or to a doubly-linked {!List}. *)
51+
and 'a cursor = At : ('a, [< `List | `Node ]) tdt -> 'a cursor [@@unboxed]
52+
53+
type 'a t = ('a, [ `List ]) tdt
3754
(** Type of a doubly-linked list containing {!node}s of type ['a]. *)
3855

39-
type !'a node
56+
type 'a node = ('a, [ `Node ]) tdt
4057
(** Type of a node containing a value of type ['a]. *)
4158

4259
val create : unit -> 'a t
@@ -58,6 +75,7 @@ module Xt :
5875
Dllist_intf.Ops
5976
with type 'a t := 'a t
6077
with type 'a node := 'a node
78+
with type 'a cursor := 'a cursor
6179
with type ('x, 'fn) fn := xt:'x Xt.t -> 'fn
6280
with type ('x, 'fn) blocking_fn := xt:'x Xt.t -> 'fn
6381
(** Explicit transaction log passing on doubly-linked lists. *)
@@ -68,6 +86,7 @@ include
6886
Dllist_intf.Ops
6987
with type 'a t := 'a t
7088
with type 'a node := 'a node
89+
with type 'a cursor := 'a cursor
7190
with type ('x, 'fn) fn := 'fn
7291
with type ('x, 'fn) blocking_fn := ?timeoutf:float -> 'fn
7392

src/kcas_data/dllist_intf.ml

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
module type Ops = sig
22
type 'a t
33
type 'a node
4+
type 'a cursor
45
type ('x, 'fn) fn
56
type ('x, 'fn) blocking_fn
67

@@ -95,4 +96,12 @@ module type Ops = sig
9596
9697
{b NOTE}: This operation is linear time, [O(n)], and should typically be
9798
avoided unless the list is privatized, e.g. by using {!take_all}. *)
99+
100+
(** {2 Operations on cursors} *)
101+
102+
val get_l : ('x, 'a cursor -> 'a cursor) fn
103+
(** [get_l c] returns the cursor to the left of the current position. *)
104+
105+
val get_r : ('x, 'a cursor -> 'a cursor) fn
106+
(** [get_r c] returns the cursor to the right of the current position. *)
98107
end

test/kcas_data/dllist_test.ml

Lines changed: 9 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,13 @@
11
open Kcas_data
22

3+
let[@tail_mod_cons] rec to_list get_lr cursor =
4+
match get_lr cursor with
5+
| Dllist.At (List _) -> []
6+
| Dllist.At (Node _ as node) ->
7+
Dllist.get node :: to_list get_lr (Dllist.At node)
8+
9+
let to_list get_lr list = to_list get_lr (Dllist.At list)
10+
311
let[@tail_mod_cons] rec take_as_list take l =
412
match take l with None -> [] | Some x -> x :: take_as_list take l
513

@@ -37,7 +45,7 @@ let add () =
3745
Dllist.add_l 1 l |> ignore;
3846
Dllist.add_l 3 l |> ignore;
3947
Dllist.add_r 4 l |> ignore;
40-
assert (take_as_list Dllist.take_opt_l l = [ 3; 1; 4 ])
48+
assert (to_list Dllist.get_r l = [ 3; 1; 4 ])
4149

4250
let move () =
4351
let t1 = Dllist.create () in

0 commit comments

Comments
 (0)