--------------------- 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 <> ReportStateInvalid == /\ state' = "INVALID_STATE" /\ UNCHANGED <> ReportContentInvalid == /\ content' = "INVALID_STATE" /\ UNCHANGED <> AllUnchanged == /\ UNCHANGED <> PollInit == CASE state = "IDLE" -> IF waker = "NotSet" THEN /\ mutWaker' = mutWaker + 1 /\ pollStep' = "ResumePollInit" /\ UNCHANGED <> ELSE ReportWakerInvalid [] OTHER -> ReportStateInvalid ResumePollInit == CASE state = "IDLE" -> IF waker = "NotSet" THEN /\ waker' = "Set" /\ UNCHANGED <> ELSE IF waker = "Set" THEN /\ mutWaker' = mutWaker - 1 /\ state' = "WAIT" /\ pollStep = "RePoll" /\ UNCHANGED <> ELSE ReportWakerInvalid [] state = "SET" -> IF waker = "NotSet" THEN /\ mutContent' = mutContent + 1 /\ pollStep' = "ResumePollInitSet" /\ UNCHANGED <> ELSE ReportWakerInvalid [] state = "WASTE" -> IF waker # "NotSet" THEN ReportWakerInvalid ELSE /\ pollStep' = "DropFuture" /\ UNCHANGED <> [] OTHER -> ReportStateInvalid ResumePollInitSet == CASE state = "SET" -> IF waker = "NotSet" THEN /\ content' = "Taken" /\ waker' = "InValid" /\ UNCHANGED <> ELSE IF waker = "InValid" THEN /\ mutContent' = mutContent - 1 /\ mutWaker' = mutWaker - 1 /\ state' = "DRAIN" /\ pollStep' = "Finish" /\ UNCHANGED <> ELSE ReportWakerInvalid [] OTHER -> ReportStateInvalid ResumeRePollReplace == CASE state = "WAIT_REPLACE" -> IF waker = "Set" THEN /\ state' = "WAIT" /\ mutWaker' = mutWaker - 1 /\ pollStep' = "RePoll" /\ UNCHANGED <> ELSE ReportWakerInvalid [] state = "SET_WAIT" -> IF waker = "Set" THEN /\ waker' = "Invalid" /\ mutContent' = content + 1 /\ UNCHANGED <> ELSE IF content # "Taken" THEN /\ content' = "Taken" /\ UNCHANGED <> ELSE IF /\ waker = "Invalid" /\ content = "Taken" THEN /\ mutWaker' = mutWaker - 1 /\ mutContent' = mutContent - 1 /\ pollStep' = "Finish" /\ state' = "DRAIN" /\ UNCHANGED <> ELSE ReportWakerInvalid [] OTHER -> ReportStateInvalid ResumeRePollSet == CASE state = "SET_WAIT" -> IF content = "Set" THEN /\ content' = "Taken" /\ UNCHANGED <> ELSE IF content = "Taken" THEN /\ mutContent' = mutContent - 1 /\ state' = "DRAIN" /\ pollStep' = "Finish" /\ UNCHANGED <> ELSE ReportContentInvalid [] OTHER -> ReportStateInvalid RePoll == CASE state = "WAIT" -> /\ state' = "WAIT_REPLACE" /\ pollStep' = "ResumeRePollReplace" /\ mutWaker' = mutWaker + 1 /\ UNCHANGED <> [] state = "SET_WAIT" -> IF content = "Set" THEN /\ mutContent' = mutContent + 1 /\ pollStep' = "ResumeRePollSet" /\ UNCHANGED <> 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 <> ELSE IF content = "InValid" THEN /\ mutContent' = mutContent - 1 /\ mutWaker' = mutWaker - 1 /\ pollStep' = "StopFuture" /\ state' = "WASTE" /\ UNCHANGED <> ELSE ReportContentInvalid ResumeDropFutureWait == IF waker = "Set" THEN /\ waker' = "InValid" /\ UNCHANGED <> ELSE IF waker = "InValid" THEN /\ mutWaker' = mutWaker - 1 /\ pollStep' = "StopFuture" /\ UNCHANGED <> ELSE ReportWakerInvalid DropFutureInit == CASE state = "IDLE" -> /\ state' = "WASTE" /\ pollStep' = "StopFuture" /\ UNCHANGED <> [] state = "SET" -> /\ mutContent' = mutContent + 1 /\ mutWaker' = mutWaker + 1 /\ pollStep' = "ResumeDropFutureSet" /\ UNCHANGED <> [] state = "SET_WAIT" -> /\ mutContent' = mutContent + 1 /\ mutWaker' = mutWaker + 1 /\ pollStep' = "ResumeDropFutureSet" /\ UNCHANGED <> [] state = "WAIT" -> /\ state' = "WASTE" /\ mutWaker' = mutWaker + 1 /\ pollStep' = "ResumeDropFutureWait" /\ UNCHANGED <> [] state = "WASTE" -> /\ mutWaker' = mutWaker + 1 /\ pollStep' = "ResumeDropFutureWait" /\ UNCHANGED <> [] state = "DRAIN" -> /\ pollStep' = "StopFuture" /\ UNCHANGED <> [] 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 <> ELSE IF content = "Set" THEN /\ state' = "SET" /\ promiseStep' = "DropPromise" /\ UNCHANGED <> ELSE ReportContentInvalid [] state = "WAIT" -> /\ promiseStep' = "ResumePromiseWait" /\ UNCHANGED <> [] OTHER -> ReportStateInvalid ResumePromiseWait == CASE state = "WAIT" -> IF content = "NotSet" THEN /\ content' = "Set" /\ mutWaker' = mutWaker + 1 /\ mutContent' = mutContent - 1 /\ UNCHANGED <> ELSE IF content = "Set" THEN /\ state' = "SET_WAIT" /\ waker' = "Taken" /\ mutWaker' = mutWaker - 1 /\ promiseStep' = "DropPromise" /\ UNCHANGED <> ELSE ReportContentInvalid [] state = "WAIT_REPLACE" -> IF content = "NotSet" THEN /\ content' = "Set" /\ mutContent' = mutContent - 1 /\ UNCHANGED <> ELSE IF content = "Set" THEN /\ state' = "SET_WAIT" /\ promiseStep' = "DropPromise" /\ UNCHANGED <> ELSE ReportContentInvalid [] OTHER -> ReportStateInvalid PromiseInit == CASE state = "IDLE" -> /\ mutContent' = mutContent + 1 /\ promiseStep' = "ResumePromiseInit" /\ UNCHANGED <> [] state = "WAIT" -> /\ mutContent' = mutContent + 1 /\ promiseStep' = "ResumePromiseWait" /\ UNCHANGED <> [] state = "WASTE" -> /\ promiseStep' = "DropPromise" /\ UNCHANGED <> [] OTHER -> ReportStateInvalid DropPromiseDirectly == /\ state' = "WASTE" /\ promiseStep' = "StopPromise" /\ UNCHANGED <> ResumeDropPromiseWait == IF waker = "Set" THEN /\ waker' = "Taken" /\ UNCHANGED <> ELSE IF waker = "Taken" THEN /\ mutWaker' = mutWaker - 1 /\ promiseStep' = "StopPromise" /\ UNCHANGED <> ELSE ReportWakerInvalid DropPromiseInit == CASE state = "IDLE" -> DropPromiseDirectly [] state = "WAIT" -> /\ state' = "WASTE" /\ mutWaker' = mutWaker + 1 /\ promiseStep' = "ResumeDropPromiseWait" /\ UNCHANGED <> [] state = "WAIT_REPLACE" -> DropPromiseDirectly [] state \in { "SET", "SET_WAIT", "DRAIN", "WASTE" } -> /\ promiseStep' = "StopPromise" /\ UNCHANGED <> [] 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 ===================================================================================================