-
Notifications
You must be signed in to change notification settings - Fork 1
/
code_mpmcqueue.v
49 lines (41 loc) · 1.66 KB
/
code_mpmcqueue.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
From gpfsl.lang Require Export notation.
From gpfsl.logic Require Import repeat_loop new_delete atomic_exchange.
Notation enq := 0 (only parsing).
Notation deq := 1 (only parsing).
Notation size := 2 (only parsing).
Notation slot := 3 (only parsing).
Section MpmcQueue.
Variables (newSEQ enqueueWithTicket dequeueWithTicket : val).
Definition initSlot : val :=
rec: "next" ["q"; "idx"; "size"] :=
if: "idx" = "size" then #☠
else "q" +ₗ "idx" <- newSEQ [];;
"next" ["q"; "idx" + #1; "size"].
Definition newQueue : val :=
λ: ["size"],
let: "q" := new [ "size" + #3] in
"q" +ₗ #enq <- #0;; (* Initialize field for [enqTicket] *)
"q" +ₗ #deq <- #0;; (* Initialize field for [deqTicket] *)
"q" +ₗ #size <- "size";;
initSlot ["q" +ₗ #slot; #0; "size"];; (* Initialize each slot *)
"q".
Definition enqueue : val :=
λ: ["q"; "v"],
let: "ticket" := FAAʳˡˣ("q" +ₗ #enq, #1) in
let: "size" := ! ("q" +ₗ #size) in
let: "turn" := "ticket" `quot` "size" in
let: "idx" := "ticket" `rem` "size" in
let: "slot" := "q" +ₗ #slot in
enqueueWithTicket [! ("slot" +ₗ "idx"); "turn"; "v"].
Definition dequeue : val :=
λ: ["q"],
let: "ticket" := FAAʳˡˣ("q" +ₗ #deq, #1) in
let: "size" := ! ("q" +ₗ #size) in
let: "turn" := "ticket" `quot` "size" in
let: "idx" := "ticket" `rem` "size" in
let: "slot" := "q" +ₗ #slot in
(** Instead of just `dequeueWithTicket`, we temporarilty store its return value
This is a little trick for taking one more step to remove later ▷ modality *)
let: "ret" := dequeueWithTicket [! ("slot" +ₗ "idx"); "turn"] in
"ret".
End MpmcQueue.