diff options
Diffstat (limited to 'theories/fin_queue_spec.v')
| -rw-r--r-- | theories/fin_queue_spec.v | 67 |
1 files changed, 67 insertions, 0 deletions
diff --git a/theories/fin_queue_spec.v b/theories/fin_queue_spec.v new file mode 100644 index 0000000..f7e0886 --- /dev/null +++ b/theories/fin_queue_spec.v | |||
| @@ -0,0 +1,67 @@ | |||
| 1 | From iris.program_logic Require Import atomic. | ||
| 2 | From iris.heap_lang Require Import notation proofmode. | ||
| 3 | |||
| 4 | From lmpmc Require Import util. | ||
| 5 | |||
| 6 | (* Doing this split because I don't know how to otherwise get a nice | ||
| 7 | closed proof. *) | ||
| 8 | |||
| 9 | Record fin_queue_hl := | ||
| 10 | FinQueueHl | ||
| 11 | { new : val; | ||
| 12 | enqueue : val; | ||
| 13 | finalize : val; | ||
| 14 | try_dequeue : val;}. | ||
| 15 | Record fin_queue_iris {Σ} `{!heapGS Σ} (hl : fin_queue_hl) := | ||
| 16 | FinQueueIris | ||
| 17 | { (** If [⊢ queue_repr ℓ vs mfin], then there is a queue at [ℓ] | ||
| 18 | which currently holds the values [vs], and possibly a final | ||
| 19 | value [mfin]. The dequeue and enqueue operations work in | ||
| 20 | FIFO fashion, with [head vs] (if any) representing the next | ||
| 21 | value that would be dequeued by a [try_dequeue ℓ] operation. | ||
| 22 | |||
| 23 | Only non-finalized queues can be enqueued in. Non-finalized queues | ||
| 24 | can be finalized using the [finalize ℓ v] operation, which sets | ||
| 25 | [mfin] to [v]. Subsequent [try_dequeue ℓ] operations then first | ||
| 26 | dequeue the remainder of [vs]; when [vs] is empty, they return [mfin] | ||
| 27 | (but, critically, do not unset it). *) | ||
| 28 | queue_repr : loc → list val → option val → iProp Σ; | ||
| 29 | #[global] queue_repr_timeless ℓ vs mfin :: Timeless (queue_repr ℓ vs mfin); | ||
| 30 | |||
| 31 | (** If [⊢ queue_fin ℓ v], then the queue at [ℓ] has been | ||
| 32 | finalized and all elements except for the final element [v] | ||
| 33 | have been dequeued. | ||
| 34 | |||
| 35 | Queues that enter this state never leave this state; this | ||
| 36 | allows [queue_fin ℓ v] to be a persistent proposition. *) | ||
| 37 | queue_fin : loc → val → iProp Σ; | ||
| 38 | #[global] queue_fin_persistent ℓ v :: Persistent (queue_fin ℓ v); | ||
| 39 | #[global] queue_fin_timeless ℓ v :: Timeless (queue_fin ℓ v); | ||
| 40 | queue_fin_obtain ℓ fin : queue_repr ℓ [] (Some fin) -∗ queue_fin ℓ fin; | ||
| 41 | queue_fin_agree ℓ vs fin mfin : | ||
| 42 | queue_fin ℓ fin -∗ | ||
| 43 | queue_repr ℓ vs mfin -∗ | ||
| 44 | ⌜vs = []⌝ ∗ ⌜mfin = Some fin⌝; | ||
| 45 | |||
| 46 | new_spec : | ||
| 47 | {{{ True }}} | ||
| 48 | hl.(new) #() | ||
| 49 | {{{ (ℓ : loc), RET #ℓ; queue_repr ℓ [] None }}}; | ||
| 50 | |||
| 51 | enqueue_spec (ℓ_q : loc) (data : val) : | ||
| 52 | ⊢ <<{ ∀∀ vs, queue_repr ℓ_q vs None }>> | ||
| 53 | hl.(enqueue) #ℓ_q data @ ∅ | ||
| 54 | <<{ queue_repr ℓ_q (vs ++ [data]) None | RET #() }>>; | ||
| 55 | |||
| 56 | finalize_spec (ℓ_q : loc) (data : val) : | ||
| 57 | ⊢ <<{ ∀∀ vs, queue_repr ℓ_q vs None }>> | ||
| 58 | hl.(finalize) #ℓ_q data @ ∅ | ||
| 59 | <<{ queue_repr ℓ_q vs (Some data) | RET #() }>>; | ||
| 60 | |||
| 61 | try_dequeue_spec (ℓ_q : loc) : | ||
| 62 | ⊢ <<{ ∀∀ vs mfin, queue_repr ℓ_q vs mfin }>> | ||
| 63 | hl.(try_dequeue) #ℓ_q @ ∅ | ||
| 64 | <<{ queue_repr ℓ_q (tail vs) mfin | ||
| 65 | | RET (if head vs is Some v then InjLV v else InjRV (val_opt_hl mfin)) }>>; | ||
| 66 | }. | ||
| 67 | #[global] Arguments fin_queue_iris _ {_} _ : assert. | ||