Skip to content

Commit 6aa2d66

Browse files
committed
Use polymorphic variants to avoid the impossible
1 parent ca8f834 commit 6aa2d66

File tree

1 file changed

+40
-48
lines changed

1 file changed

+40
-48
lines changed

src/michael_scott_queue.ml

Lines changed: 40 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -18,32 +18,30 @@
1818

1919
(* Michael-Scott queue *)
2020

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+
}
2327

2428
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
2731
{ head = Atomic.make head; tail = Atomic.make tail }
2832

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
3336

34-
let pop q =
37+
let pop { head; _ } =
3538
let b = Backoff.create () in
3639
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)) ->
4745
Some v
4846
| _ ->
4947
Backoff.once b;
@@ -54,40 +52,35 @@ let pop q =
5452
let rec fix_tail tail old_tail new_tail =
5553
if Atomic.compare_and_set tail old_tail new_tail then
5654
match Atomic.get new_tail with
57-
| Nil -> ()
58-
| Next (_, new_new_tail) -> fix_tail tail new_tail new_new_tail
55+
| `Nil -> ()
56+
| `Node (_, new_new_tail) -> fix_tail tail new_tail new_new_tail
5957

60-
let push q v =
58+
let push { tail; _ } v =
6159
let rec find_tail_and_enq curr_end node =
62-
if Atomic.compare_and_set curr_end Nil node then ()
60+
if Atomic.compare_and_set curr_end `Nil node then ()
6361
else
6462
match Atomic.get curr_end with
65-
| Nil -> find_tail_and_enq curr_end node
66-
| Next (_, n) -> find_tail_and_enq n node
63+
| `Nil -> find_tail_and_enq curr_end node
64+
| `Node (_, n) -> find_tail_and_enq n node
6765
in
68-
let new_tail = Atomic.make Nil in
69-
let newnode = Next (v, new_tail) in
70-
let old_tail = Atomic.get q.tail in
66+
let new_tail = Atomic.make `Nil in
67+
let newnode = `Node (v, new_tail) in
68+
let old_tail = Atomic.get tail in
7169
find_tail_and_enq old_tail newnode;
72-
if Atomic.compare_and_set q.tail old_tail new_tail then
70+
if Atomic.compare_and_set tail old_tail new_tail then
7371
match Atomic.get new_tail with
74-
| Nil -> ()
75-
| Next (_, new_new_tail) -> fix_tail q.tail new_tail new_new_tail
72+
| `Nil -> ()
73+
| `Node (_, new_new_tail) -> fix_tail tail new_tail new_new_tail
7674

77-
let clean_until q f =
75+
let clean_until { head; _ } f =
7876
let b = Backoff.create () in
7977
let rec loop () =
80-
let s = Atomic.get q.head in
81-
let nhead =
82-
match s with
83-
| Nil -> failwith "MSQueue.pop: impossible"
84-
| Next (_, x) -> Atomic.get x
85-
in
86-
match nhead with
87-
| Nil -> ()
88-
| Next (v, x) ->
78+
let (`Node (_, x) as old_head) = Atomic.get head in
79+
match Atomic.get x with
80+
| `Nil -> ()
81+
| `Node (v, x) ->
8982
if not (f v) then
90-
if Atomic.compare_and_set q.head s (Next (Obj.magic (), x)) then (
83+
if Atomic.compare_and_set head old_head (`Node (Obj.magic (), x)) then (
9184
Backoff.reset b;
9285
loop ())
9386
else (
@@ -97,11 +90,10 @@ let clean_until q f =
9790
in
9891
loop ()
9992

100-
type 'a cursor = 'a node
93+
type 'a cursor = [ `Nil | `Node of 'a node ]
10194

102-
let snapshot q =
103-
match Atomic.get q.head with
104-
| Nil -> failwith "MSQueue.snapshot: impossible"
105-
| Next (_, n) -> Atomic.get n
95+
let snapshot { head; _ } =
96+
let (`Node (_, n)) = Atomic.get head in
97+
Atomic.get n
10698

107-
let next c = match c with Nil -> None | Next (a, n) -> Some (a, Atomic.get n)
99+
let next = function `Nil -> None | `Node (a, n) -> Some (a, Atomic.get n)

0 commit comments

Comments
 (0)