Skip to content

Commit 38056f6

Browse files
committed
Use polymorphic variants to avoid the impossible
1 parent a9552be commit 38056f6

File tree

1 file changed

+36
-44
lines changed

1 file changed

+36
-44
lines changed

src/michael_scott_queue.ml

Lines changed: 36 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -18,67 +18,60 @@
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;
5048
loop ()
5149
in
5250
loop ()
5351

54-
let push q v =
52+
let push { tail; _ } v =
5553
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 ()
5755
else
5856
match Atomic.get curr_end with
59-
| Nil -> find_tail_and_enq curr_end node
60-
| Next (_, n) -> find_tail_and_enq n node
57+
| `Nil -> find_tail_and_enq curr_end node
58+
| `Node (_, n) -> find_tail_and_enq n node
6159
in
62-
let new_tail = Atomic.make Nil in
63-
let newnode = Next (v, new_tail) in
64-
let old_tail = Atomic.get q.tail in
60+
let new_tail = Atomic.make `Nil in
61+
let newnode = `Node (v, new_tail) in
62+
let old_tail = Atomic.get tail in
6563
find_tail_and_enq old_tail newnode;
66-
ignore (Atomic.compare_and_set q.tail old_tail new_tail)
64+
ignore (Atomic.compare_and_set tail old_tail new_tail)
6765

68-
let clean_until q f =
66+
let clean_until { head; _ } f =
6967
let b = Backoff.create () in
7068
let rec loop () =
71-
let s = Atomic.get q.head in
72-
let nhead =
73-
match s with
74-
| Nil -> failwith "MSQueue.pop: impossible"
75-
| Next (_, x) -> Atomic.get x
76-
in
77-
match nhead with
78-
| Nil -> ()
79-
| Next (v, x) ->
69+
let (`Node (_, x) as old_head) = Atomic.get head in
70+
match Atomic.get x with
71+
| `Nil -> ()
72+
| `Node (v, x) ->
8073
if not (f v) then
81-
if Atomic.compare_and_set q.head s (Next (Obj.magic (), x)) then (
74+
if Atomic.compare_and_set head old_head (`Node (Obj.magic (), x)) then (
8275
Backoff.reset b;
8376
loop ())
8477
else (
@@ -88,11 +81,10 @@ let clean_until q f =
8881
in
8982
loop ()
9083

91-
type 'a cursor = 'a node
84+
type 'a cursor = [ `Nil | `Node of 'a node ]
9285

93-
let snapshot q =
94-
match Atomic.get q.head with
95-
| Nil -> failwith "MSQueue.snapshot: impossible"
96-
| Next (_, n) -> Atomic.get n
86+
let snapshot { head; _ } =
87+
let (`Node (_, n)) = Atomic.get head in
88+
Atomic.get n
9789

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

0 commit comments

Comments
 (0)