18
18
19
19
(* Michael-Scott queue *)
20
20
21
- type 'a node = Nil | Next of 'a * 'a node Atomic .t
22
- type 'a t = { head : 'a node Atomic .t ; tail : 'a node Atomic .t Atomic .t }
21
+ type 'a node = 'a * [ `Nil | `Node of 'a node ] Atomic .t
22
+
23
+ type 'a t = {
24
+ head : [ `Node of 'a node ] Atomic .t ;
25
+ tail : [ `Nil | `Node of 'a node ] Atomic .t Atomic .t ;
26
+ }
23
27
24
28
let create () =
25
- let tail = Atomic. make Nil in
26
- let head = Next (Obj. magic () , tail) in
29
+ let tail = Atomic. make ` Nil in
30
+ let head = `Node (Obj. magic () , tail) in
27
31
{ head = Atomic. make head; tail = Atomic. make tail }
28
32
29
- let is_empty q =
30
- match Atomic. get q.head with
31
- | Nil -> failwith " MSQueue.is_empty: impossible"
32
- | Next (_ , x ) -> ( match Atomic. get x with Nil -> true | _ -> false )
33
+ let is_empty { head; _ } =
34
+ let (`Node (_, x)) = Atomic. get head in
35
+ Atomic. get x == `Nil
33
36
34
- let pop q =
37
+ let pop { head; _ } =
35
38
let b = Backoff. create () in
36
39
let rec loop () =
37
- let s = Atomic. get q.head in
38
- let nhead =
39
- match s with
40
- | Nil -> failwith " MSQueue.pop: impossible"
41
- | Next (_ , x ) -> Atomic. get x
42
- in
43
- match nhead with
44
- | Nil -> None
45
- | Next (v, x) when Atomic. compare_and_set q.head s (Next (Obj. magic () , x))
46
- ->
40
+ let (`Node (_, x) as old_head ) = Atomic. get head in
41
+ match Atomic. get x with
42
+ | `Nil -> None
43
+ | `Node (v, x)
44
+ when Atomic. compare_and_set head old_head (`Node (Obj. magic () , x)) ->
47
45
Some v
48
46
| _ ->
49
47
Backoff. once b;
50
48
loop ()
51
49
in
52
50
loop ()
53
51
54
- let push q v =
52
+ let push { tail; _ } v =
55
53
let rec find_tail_and_enq curr_end node =
56
- if Atomic. compare_and_set curr_end Nil node then ()
54
+ if Atomic. compare_and_set curr_end ` Nil node then ()
57
55
else
58
56
match Atomic. get curr_end with
59
- | Nil -> find_tail_and_enq curr_end node
60
- | Next (_ , n ) ->
57
+ | ` Nil -> find_tail_and_enq curr_end node
58
+ | `Node (_ , n ) ->
61
59
(* If tail falls behind, there is a risk of space leak. *)
62
- ignore (Atomic. compare_and_set q. tail curr_end n);
60
+ ignore (Atomic. compare_and_set tail curr_end n);
63
61
find_tail_and_enq n node
64
62
in
65
- let new_tail = Atomic. make Nil in
66
- let newnode = Next (v, new_tail) in
67
- let old_tail = Atomic. get q. tail in
63
+ let new_tail = Atomic. make ` Nil in
64
+ let newnode = `Node (v, new_tail) in
65
+ let old_tail = Atomic. get tail in
68
66
find_tail_and_enq old_tail newnode;
69
- ignore (Atomic. compare_and_set q. tail old_tail new_tail)
67
+ ignore (Atomic. compare_and_set tail old_tail new_tail)
70
68
71
- let clean_until q f =
69
+ let clean_until { head; _ } f =
72
70
let b = Backoff. create () in
73
71
let rec loop () =
74
- let s = Atomic. get q.head in
75
- let nhead =
76
- match s with
77
- | Nil -> failwith " MSQueue.pop: impossible"
78
- | Next (_ , x ) -> Atomic. get x
79
- in
80
- match nhead with
81
- | Nil -> ()
82
- | Next (v , x ) ->
72
+ let (`Node (_, x) as old_head ) = Atomic. get head in
73
+ match Atomic. get x with
74
+ | `Nil -> ()
75
+ | `Node (v , x ) ->
83
76
if not (f v) then
84
- if Atomic. compare_and_set q. head s ( Next (Obj. magic () , x)) then (
77
+ if Atomic. compare_and_set head old_head ( `Node (Obj. magic () , x)) then (
85
78
Backoff. reset b;
86
79
loop () )
87
80
else (
@@ -91,11 +84,10 @@ let clean_until q f =
91
84
in
92
85
loop ()
93
86
94
- type 'a cursor = 'a node
87
+ type 'a cursor = [ `Nil | `Node of 'a node ]
95
88
96
- let snapshot q =
97
- match Atomic. get q.head with
98
- | Nil -> failwith " MSQueue.snapshot: impossible"
99
- | Next (_ , n ) -> Atomic. get n
89
+ let snapshot { head; _ } =
90
+ let (`Node (_, n)) = Atomic. get head in
91
+ Atomic. get n
100
92
101
- let next c = match c with Nil -> None | Next (a , n ) -> Some (a, Atomic. get n)
93
+ let next = function ` Nil -> None | `Node (a , n ) -> Some (a, Atomic. get n)
0 commit comments