safe_drive 0.4.3

safe_drive: Formally Specified Rust Bindings for ROS2
Documentation
---- MODULE init_once ----
EXTENDS TLC, FiniteSets, Integers

CONSTANTS Processes

(* --algorithm init_once
variables
    lock = FALSE;
    is_init = FALSE;

    pids = {};

define
    just_once == <>[](Cardinality(pids) = 1) /\ [](Cardinality(pids) <= 1)
end define

\* initializer
fair+ process pid \in Processes
begin
    BeginInitOnce:
        while ~is_init do
            LoadLockRelaxed:
                if ~lock then
                    CompareExchange:
                        if ~lock then
                            lock := TRUE;
                            pids := pids \union {self};

                            Initialize:
                                skip;

                            StoreIsInit:
                                is_init := TRUE;
                        end if;
                end if;
        end while;
end process;

end algorithm; *)
\* BEGIN TRANSLATION (chksum(pcal) = "171ee2b4" /\ chksum(tla) = "1cd14bb5")
VARIABLES lock, is_init, pids, pc

(* define statement *)
just_once == <>[](Cardinality(pids) = 1) /\ [](Cardinality(pids) <= 1)


vars == << lock, is_init, pids, pc >>

ProcSet == (Processes)

Init == (* Global variables *)
        /\ lock = FALSE
        /\ is_init = FALSE
        /\ pids = {}
        /\ pc = [self \in ProcSet |-> "BeginInitOnce"]

BeginInitOnce(self) == /\ pc[self] = "BeginInitOnce"
                       /\ IF ~is_init
                             THEN /\ pc' = [pc EXCEPT ![self] = "LoadLockRelaxed"]
                             ELSE /\ pc' = [pc EXCEPT ![self] = "Done"]
                       /\ UNCHANGED << lock, is_init, pids >>

LoadLockRelaxed(self) == /\ pc[self] = "LoadLockRelaxed"
                         /\ IF ~lock
                               THEN /\ pc' = [pc EXCEPT ![self] = "CompareExchange"]
                               ELSE /\ pc' = [pc EXCEPT ![self] = "BeginInitOnce"]
                         /\ UNCHANGED << lock, is_init, pids >>

CompareExchange(self) == /\ pc[self] = "CompareExchange"
                         /\ IF ~lock
                               THEN /\ lock' = TRUE
                                    /\ pids' = (pids \union {self})
                                    /\ pc' = [pc EXCEPT ![self] = "Initialize"]
                               ELSE /\ pc' = [pc EXCEPT ![self] = "BeginInitOnce"]
                                    /\ UNCHANGED << lock, pids >>
                         /\ UNCHANGED is_init

Initialize(self) == /\ pc[self] = "Initialize"
                    /\ TRUE
                    /\ pc' = [pc EXCEPT ![self] = "StoreIsInit"]
                    /\ UNCHANGED << lock, is_init, pids >>

StoreIsInit(self) == /\ pc[self] = "StoreIsInit"
                     /\ is_init' = TRUE
                     /\ pc' = [pc EXCEPT ![self] = "BeginInitOnce"]
                     /\ UNCHANGED << lock, pids >>

pid(self) == BeginInitOnce(self) \/ LoadLockRelaxed(self)
                \/ CompareExchange(self) \/ Initialize(self)
                \/ StoreIsInit(self)

(* Allow infinite stuttering to prevent deadlock on termination. *)
Terminating == /\ \A self \in ProcSet: pc[self] = "Done"
               /\ UNCHANGED vars

Next == (\E self \in Processes: pid(self))
           \/ Terminating

Spec == /\ Init /\ [][Next]_vars
        /\ \A self \in Processes : SF_vars(pid(self))

Termination == <>(\A self \in ProcSet: pc[self] = "Done")

\* END TRANSLATION
====