mrwei 0.1.0

A simple library that implements the common promise primitive for rust based on std future.
Documentation
--------------------- MODULE mrwei ---------------------------

EXTENDS Integers

VARIABLES state, content, waker, mutWaker, mutContent, pollStep, promiseStep

ALL_STATES == { "IDLE", "SET", "SET_WAIT", "WAIT", "WAIT_REPLACE", "DRAIN", "WASTE" }

POSSIBLE_STATE == { "NotSet", "Set", "Taken", "InValid" }

ALL_POLL_STEPS == {  "Init", "RePoll", "ResumePollInit", "ResumeRePollReplace", "ResumeRePollSet", "ResumePollInitSet", "Finish", "ResumeDropFutureSet", "ResumeDropFutureWait" }
ALL_PROMISE_STEPS == { "Init", "ResumePromiseInit", "ResumePromiseWait", "DropPromise", "ResumeDropPromiseWait", "StopPromise" }

TypeInvarint == /\ state \in ALL_STATES
                /\ content \in POSSIBLE_STATE
                /\ waker \in POSSIBLE_STATE
                /\ mutWaker \in Nat
                /\ mutContent \in Nat

Init == /\ state = "IDLE"
        /\ content = "NotSet"
        /\ waker = "NotSet"
        /\ mutWaker = 0
        /\ mutContent = 0
        /\ pollStep = "Init"
        /\ promiseStep = "Init"

ReportWakerInvalid ==
    /\ waker' = "INVALID_STATE"
    /\ UNCHANGED <<state, content, mutContent, mutWaker, pollStep, promiseStep>>

ReportStateInvalid ==
    /\ state' = "INVALID_STATE"
    /\ UNCHANGED <<waker, content, mutContent, mutWaker, pollStep, promiseStep>>

ReportContentInvalid ==
    /\ content' = "INVALID_STATE"
    /\ UNCHANGED <<state, waker, mutContent, mutWaker, pollStep, promiseStep>>

AllUnchanged ==
    /\ UNCHANGED <<state, content, mutContent, waker, mutWaker, pollStep, promiseStep>>

PollInit == CASE state = "IDLE" ->
                IF waker = "NotSet" THEN
                    /\ mutWaker' = mutWaker + 1
                    /\ pollStep' = "ResumePollInit"
                    /\ UNCHANGED <<state, waker, content, mutContent, promiseStep>>
                ELSE ReportWakerInvalid
              [] OTHER -> ReportStateInvalid

ResumePollInit ==
    CASE state = "IDLE" ->
          IF waker = "NotSet" THEN
              /\ waker' = "Set"
              /\ UNCHANGED <<state, content, mutWaker, mutContent, pollStep, promiseStep>>
          ELSE IF waker = "Set" THEN 
              /\ mutWaker' = mutWaker - 1
              /\ state' = "WAIT"
              /\ pollStep = "RePoll"
              /\ UNCHANGED <<content, waker, mutContent, pollStep, promiseStep>>
          ELSE ReportWakerInvalid
      [] state = "SET" ->
          IF waker = "NotSet" THEN
              /\ mutContent' = mutContent + 1
              /\ pollStep' = "ResumePollInitSet"
              /\ UNCHANGED <<state, content, waker, mutWaker, promiseStep>>
          ELSE ReportWakerInvalid
      [] state = "WASTE" ->
           IF waker # "NotSet" THEN ReportWakerInvalid
           ELSE /\ pollStep' = "DropFuture"
                /\ UNCHANGED <<state, content, waker, mutContent, mutWaker, promiseStep>>
      [] OTHER -> ReportStateInvalid

ResumePollInitSet ==
    CASE state = "SET" ->
          IF waker = "NotSet" THEN
              /\ content' = "Taken"
              /\ waker' = "InValid"
              /\ UNCHANGED <<state, mutContent, mutWaker, pollStep, promiseStep>>
          ELSE IF waker = "InValid" THEN
              /\ mutContent' = mutContent - 1
              /\ mutWaker' = mutWaker - 1
              /\ state' = "DRAIN"
              /\ pollStep' = "Finish"
              /\ UNCHANGED <<content, waker, promiseStep>>
          ELSE ReportWakerInvalid
      [] OTHER -> ReportStateInvalid     

ResumeRePollReplace ==
    CASE state = "WAIT_REPLACE" ->
          IF waker = "Set" THEN
              /\ state' = "WAIT"
              /\ mutWaker' = mutWaker - 1
              /\ pollStep' = "RePoll"
              /\ UNCHANGED <<content, mutContent, waker, promiseStep>>
          ELSE ReportWakerInvalid
      [] state = "SET_WAIT" ->
          IF waker = "Set" THEN
              /\ waker' = "Invalid"
              /\ mutContent' = content + 1
              /\ UNCHANGED <<state, content, mutWaker, pollStep, promiseStep>>
          ELSE IF content # "Taken" THEN
              /\ content' = "Taken"
              /\ UNCHANGED <<state, waker, mutWaker, mutContent, pollStep, promiseStep>>
          ELSE IF /\ waker = "Invalid" /\ content = "Taken" THEN
              /\ mutWaker' = mutWaker - 1
              /\ mutContent' = mutContent - 1
              /\ pollStep' = "Finish"
              /\ state' = "DRAIN"
              /\ UNCHANGED <<waker, promiseStep>>
          ELSE ReportWakerInvalid
      [] OTHER -> ReportStateInvalid

ResumeRePollSet ==
    CASE state = "SET_WAIT" ->
          IF content = "Set" THEN
              /\ content' = "Taken"
              /\ UNCHANGED <<state, waker, mutContent, mutWaker, pollStep, promiseStep>>
          ELSE IF content = "Taken" THEN
              /\ mutContent' = mutContent - 1
              /\ state' = "DRAIN"
              /\ pollStep' = "Finish"
              /\ UNCHANGED <<content, waker, mutWaker, promiseStep>>
          ELSE ReportContentInvalid
      [] OTHER -> ReportStateInvalid

RePoll == CASE state = "WAIT" ->
              /\ state' = "WAIT_REPLACE"
              /\ pollStep' = "ResumeRePollReplace"
              /\ mutWaker' = mutWaker + 1
              /\ UNCHANGED <<content, waker, mutContent, pollStep, promiseStep>>
            [] state = "SET_WAIT" ->
                IF content = "Set" THEN
                    /\ mutContent' = mutContent + 1
                    /\ pollStep' = "ResumeRePollSet"
                    /\ UNCHANGED <<state, waker, content, mutWaker, promiseStep>>
                ELSE ReportContentInvalid
            [] state = "DRAIN" -> AllUnchanged
            [] OTHER -> ReportStateInvalid

PollFinish == IF state = "DRAINED" THEN AllUnchanged
              ELSE ReportStateInvalid

Poll == CASE pollStep = "Init" -> PollInit
          [] pollStep = "RePoll" -> RePoll
          [] pollStep = "ResumePollInit" -> ResumePollInit
          [] pollStep = "ResumeRePollReplace" -> ResumeRePollReplace
          [] pollStep = "ResumeRePollSet" -> ResumeRePollSet
          [] pollStep = "ResumePollInitSet" -> ResumePollInitSet
          [] pollStep = "Finish" -> PollFinish
          [] OTHER -> AllUnchanged

ResumeDropFutureSet ==
    IF content = "Set" THEN
        /\ content' = "InValid"
        /\ waker' = "InValid"
        /\ UNCHANGED <<state, mutContent, mutWaker, pollStep, promiseStep>>
    ELSE IF content = "InValid" THEN
        /\ mutContent' = mutContent - 1
        /\ mutWaker' = mutWaker - 1
        /\ pollStep' = "StopFuture"
        /\ state' = "WASTE"
        /\ UNCHANGED <<waker, content, promiseStep>>
    ELSE ReportContentInvalid

ResumeDropFutureWait ==
    IF waker = "Set" THEN
        /\ waker' = "InValid"
        /\ UNCHANGED <<state, content, mutContent, mutWaker, pollStep, promiseStep>>
    ELSE IF waker = "InValid" THEN
        /\ mutWaker' = mutWaker - 1
        /\ pollStep' = "StopFuture"
        /\ UNCHANGED <<state, content, mutContent, waker, promiseStep>>
    ELSE ReportWakerInvalid

DropFutureInit ==
    CASE state = "IDLE" ->
          /\ state' = "WASTE"
          /\ pollStep' = "StopFuture"
          /\ UNCHANGED <<content, waker, mutContent, mutWaker, promiseStep>>
      [] state = "SET" ->
          /\ mutContent' = mutContent + 1
          /\ mutWaker' = mutWaker + 1
          /\ pollStep' = "ResumeDropFutureSet"
          /\ UNCHANGED <<state, content, waker, promiseStep>>
      [] state = "SET_WAIT" ->
          /\ mutContent' = mutContent + 1
          /\ mutWaker' = mutWaker + 1
          /\ pollStep' = "ResumeDropFutureSet"
          /\ UNCHANGED <<state, content, waker, mutWaker, promiseStep>>
      [] state = "WAIT" ->
          /\ state' = "WASTE"
          /\ mutWaker' = mutWaker + 1
          /\ pollStep' = "ResumeDropFutureWait"
          /\ UNCHANGED <<content, waker, mutContent, promiseStep>>
      [] state = "WASTE" ->
          /\ mutWaker' = mutWaker + 1
          /\ pollStep' = "ResumeDropFutureWait"
          /\ UNCHANGED <<state, content, waker, mutContent, promiseStep>>
      [] state = "DRAIN" ->
          /\ pollStep' = "StopFuture"
          /\ UNCHANGED <<state, content, waker, mutContent, mutWaker, promiseStep>>
      [] OTHER -> ReportStateInvalid


DropFuture == CASE pollStep = "Init" -> DropFutureInit
                [] pollStep = "RePoll" -> DropFutureInit
                [] pollStep = "Finish" -> DropFutureInit
                [] pollStep = "ResumeDropFutureSet" -> ResumeDropFutureSet
                [] pollStep = "ResumeDropFutureWait" -> ResumeDropFutureWait
                [] OTHER -> AllUnchanged

ResumePromiseInit ==
    CASE state = "IDLE" ->
          IF content = "NotSet" THEN
              /\ content' = "Set"
              /\ mutContent' = mutContent - 1
              /\ UNCHANGED <<state, waker, mutWaker, pollStep, promiseStep>>
          ELSE IF content = "Set" THEN
              /\ state' = "SET"
              /\ promiseStep' = "DropPromise"
              /\ UNCHANGED <<waker, mutWaker, content, mutContent, pollStep>>
          ELSE ReportContentInvalid
      [] state = "WAIT" ->
          /\ promiseStep' = "ResumePromiseWait"
          /\ UNCHANGED <<state, content, mutContent, waker, mutWaker, pollStep>>
       [] OTHER -> ReportStateInvalid

ResumePromiseWait ==
    CASE state = "WAIT" ->
          IF content = "NotSet" THEN
              /\ content' = "Set"
              /\ mutWaker' = mutWaker + 1
              /\ mutContent' = mutContent - 1
              /\ UNCHANGED <<state, waker, pollStep, promiseStep>>
          ELSE IF content = "Set" THEN
              /\ state' = "SET_WAIT"
              /\ waker' = "Taken"
              /\ mutWaker' = mutWaker - 1
              /\ promiseStep' = "DropPromise"
              /\ UNCHANGED <<content, mutContent, pollStep>>
          ELSE ReportContentInvalid
      [] state = "WAIT_REPLACE" ->
          IF content = "NotSet" THEN
              /\ content' = "Set"
              /\ mutContent' = mutContent - 1
              /\ UNCHANGED <<state, waker, mutWaker, pollStep, promiseStep>>
          ELSE IF content = "Set" THEN
              /\ state' = "SET_WAIT"
              /\ promiseStep' = "DropPromise"
              /\ UNCHANGED <<content, mutContent, waker, mutWaker, pollStep>>
          ELSE ReportContentInvalid
       [] OTHER -> ReportStateInvalid

PromiseInit ==
    CASE state = "IDLE" ->
          /\ mutContent' = mutContent + 1
          /\ promiseStep' = "ResumePromiseInit"
          /\ UNCHANGED <<state, content, waker, mutWaker, pollStep>>
      [] state = "WAIT" ->
          /\ mutContent' = mutContent + 1
          /\ promiseStep' = "ResumePromiseWait"
          /\ UNCHANGED <<state, content, waker, mutWaker, pollStep>>
      [] state = "WASTE" ->
          /\ promiseStep' = "DropPromise"
          /\ UNCHANGED <<state, content, waker, mutContent, mutWaker, pollStep>>
      [] OTHER -> ReportStateInvalid

DropPromiseDirectly ==
    /\ state' = "WASTE"
    /\ promiseStep' = "StopPromise"
    /\ UNCHANGED <<content, waker, mutContent, mutWaker, pollStep>>

ResumeDropPromiseWait ==
    IF waker = "Set" THEN
        /\ waker' = "Taken"
        /\ UNCHANGED <<state, content, mutContent, mutWaker, pollStep, promiseStep>>
    ELSE IF waker = "Taken" THEN
        /\ mutWaker' = mutWaker - 1
        /\ promiseStep' = "StopPromise"
        /\ UNCHANGED <<state, content, mutContent, waker, pollStep>>
    ELSE ReportWakerInvalid

DropPromiseInit ==
    CASE state = "IDLE" -> DropPromiseDirectly
      [] state = "WAIT" ->
          /\ state' = "WASTE"
          /\ mutWaker' = mutWaker + 1
          /\ promiseStep' = "ResumeDropPromiseWait"
          /\ UNCHANGED <<content, waker, mutContent, pollStep>>
      [] state = "WAIT_REPLACE" -> DropPromiseDirectly
      [] state \in { "SET", "SET_WAIT", "DRAIN", "WASTE" } ->
          /\ promiseStep' = "StopPromise"
          /\ UNCHANGED <<state, content, mutContent, waker, mutWaker, pollStep>>
      [] OTHER -> ReportStateInvalid

DropPromise ==
    CASE promiseStep = "Init" -> DropPromiseInit
      [] promiseStep = "DropPromise" -> DropPromiseInit
      [] promiseStep = "ResumeDropPromiseWait" -> ResumeDropPromiseWait
      [] OTHER -> AllUnchanged

Promise ==
    CASE promiseStep = "Init" -> PromiseInit
      [] promiseStep = "ResumePromiseInit" -> ResumePromiseInit
      [] promiseStep = "ResumePromiseWait" -> ResumePromiseWait
      [] OTHER -> AllUnchanged

Next == \/ Poll
        \/ DropFuture
        \/ Promise
        \/ DropPromise

UnreachableState == /\ \/ state \notin { "SET", "SET_WAIT" }
                       \/ content # "NotSet"
                    /\ \/ state \notin { "WAIT", "WAIT_REPLACE" }
                       \/ waker = "Set"
                    /\ mutContent \in { 0, 1 }
                    /\ mutWaker \in { 0, 1 }

ResourceDrop ==
    \/ pollStep # "StopFuture"
    \/ promiseStep # "StopPromise"
    \/ /\ content \in {"InValid", "NotSet", "Taken"}
       /\ waker \in {"InValid", "NotSet", "Taken"}
       /\ state \in { "WASTE", "DRAIN" }
       /\ mutContent = 0
       /\ mutWaker = 0
===================================================================================================