Documentation

Mt.Task.Validation

Equations
  • Mt.TaskM.instIsReservationReservation = spec.is_reservation
def Mt.TaskM.valid {spec : Mt.Spec} {T : Type} (p : Mt.TaskM spec T) (r : spec.Reservation) (assuming : spec.StateBool) (motive : Tspec.ReservationProp) :
Prop

Validation primitive for reasoning for composable tasks.

Validation may assume assuming and must ensure the following:

  • The task has to behave conform to the specification at all times
  • The task never panics
  • Finally, motive holds after the task completes

Proving valid #

The definition is rather cumbersome to work with. You should use helper theorems like valid_pure, valid_bind, valid_rmr, ...

They are designed to be used with the apply tactic.

Blocking predicate: assuming #

When validating our task, we can assume assuming state = true. However, in most cases we have assuming = λ _ => true, i.e. our hypothesis does not provide anything useful.

There is one important exception: Blocking threads. If a thread waits for a certain condition before it continues its task, we can safely assume that this condition holds when the task is excuting.

Final goal: motive #

A valid thread must drop its reservations in the end. Therefore, the final goal on those tasks is λ _ r => r = IsReservation.empty. However, intermediate tasks (i.e. single operations) do not need to share this goal.

In fact, they usally do not. If one operation prepares the next operation, it usually creates some reservation to ensure that no other thread undos this preparation. In this example, the motive should encode that the preparation has been made.

motive is the only way to pass facts from one iteration to the next. See valid_bind for more information.

Equations
  • One or more equations did not get rendered due to their size.
theorem Mt.TaskM.valid_pure {spec : Mt.Spec} {T : Type} {t : T} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Tspec.ReservationProp} (is_valid : motive t r) :
Mt.TaskM.valid (pure t) r assuming motive

To prove that pure t is valid you need to prove that the motive holds

theorem Mt.TaskM.valid_bind {spec : Mt.Spec} {U : Type} {V : Type} {mu : Mt.TaskM spec U} {f : UMt.TaskM spec V} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Vspec.ReservationProp} (motive_u : Uspec.ReservationProp) (mu_valid : Mt.TaskM.valid mu r assuming motive_u) (f_valid : ∀ (r' : spec.Reservation) (u : U), motive_u u r'Mt.TaskM.valid (f u) r' (fun x => true) motive) :
Mt.TaskM.valid (mu >>= f) r assuming motive

To prove that a >>= f is valid you need to prove that both a and f u for all results u are valid.

In many cases, a does something to prepare f u. Since only f u needs to fulfil the final motive, we can choose an arbitrary motive to validate a as "intermediate goal".

To validate f u with the original motive, we can use the fact that the intermediate goal motive_u has been ensured by a. Motives use only results and reservations, which cannot be changed by other threads. Therefore, they stay valid even if other threads become active between a and f u.

theorem Mt.TaskM.valid_rmr {spec : Mt.Spec} {T : Type} {f : spec.StateT × spec.State} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Tspec.ReservationProp} (f_valid : ∀ (env_r : spec.Reservation) (s : spec.State), assuming s = trueMt.Spec.validate spec (env_r + r) sr', let _discr := f s; match f s with | (t, s') => Mt.Spec.validate spec (env_r + r') s' motive t r') :
theorem Mt.TaskM.valid_rm {spec : Mt.Spec} {f : spec.Statespec.State} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Unitspec.ReservationProp} (f_valid : ∀ (env_r : spec.Reservation) (s : spec.State), assuming s = trueMt.Spec.validate spec (env_r + r) sr', let s' := f s; Mt.Spec.validate spec (env_r + r') s' motive PUnit.unit r') :
theorem Mt.TaskM.valid_read {spec : Mt.Spec} {T : Type} {f : spec.StateT} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Tspec.ReservationProp} (f_valid : ∀ (env_r : spec.Reservation) (s : spec.State), assuming s = trueMt.Spec.validate spec (env_r + r) sr', let t := f s; Mt.Spec.validate spec (env_r + r') s motive t r') :
Mt.TaskM.valid (Mt.TaskM.atomic_read f) r assuming motive
theorem Mt.TaskM.valid_assert {spec : Mt.Spec} {cond : spec.StateBool} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Unitspec.ReservationProp} (motive_holds : motive PUnit.unit r) (assertion_succeeds : ∀ (env_r : spec.Reservation) (s : spec.State), assuming s = trueMt.Spec.validate spec (env_r + r) scond s = true) :
Mt.TaskM.valid (Mt.TaskM.atomic_assert cond) r assuming motive
theorem Mt.TaskM.valid_blocking_rmr {spec : Mt.Spec} {T : Type} {block_until : spec.StateBool} {f : spec.StateT × spec.State} {r : spec.Reservation} {assuming : spec.StateBool} {motive : Tspec.ReservationProp} (f_valid : ∀ (env_r : spec.Reservation) (s : spec.State), block_until s = trueMt.Spec.validate spec (env_r + r) sr', let _discr := f s; match f s with | (t, s') => Mt.Spec.validate spec (env_r + r') s' motive t r') :
Mt.TaskM.valid (Mt.TaskM.atomic_blocking_rmr block_until f) r assuming motive