Formalne przekształcenie do PROMELI

     Przestrzeń stanów

#define NO_PROPS 2
#define NO_EVENTS 2
#define NO_TASKS 3
ilość nazw właściwości (rozmiar BD i tablicy blokad)
ilość zdarzeń (Memory_Event, Snarf_Event)
ilość zadań (demon + dwa zadania aplikacji systemu)

type
    EventId = {MEMORY_EVENT,SNARF_EVENT};
    TaskId = byte;

type
    Property_Name = byte;
    Property_Value = byte;

typedef Property {
    Property_Name name;
    Property_Value value};

typedef Lock {
    Property_Value value;
    list sub = [NO_TASKS] of TaskId;
    bool achieved};

typedef Event {
    byte count;
    list pending_tasks = [NO_TASKS] of TaskId};

typedef Task {
    State state;
    list waiting_for = [NO_EVENTS] of EventId;
    Property prop};

type
State = {SUSPENDED, RUNNING, ABORTED, TERMINATED};

     Zdarzenia

     Oczekiwanie na zdarzenie

inline wait_for_event(this,a,p) {
   atomic{
     append(this, Ev[a].pending_ tasks);
     append(a,active tasks[this].waiting for);
     active_tasks [this].prop.name = p.name;
     active_tasks [this].prop.value = p.value;
     active_tasks [this].state = SUSPENDED;
     active_tasks [this].state == RUNNING
     }
  }

     Oczekiwanie na sygnał

inline signal_event(a) {
   atomic{
     TaskId t;
     EventId e;
     list pending = [NO_EVENTS] of EventId;
     Ev[a] .count = Ev[a].count + 1;
     copy(Ev[a].pending_tasks,pending);
     do
     :: pending?t ->
       if
       :: (active_tasks[t].prop.value == undef_value
         ||
         db_query(active_tasks[t].prop) )
        ->
        do
        :: active_tasks[t].waiting_for?e
         -> remove(t,Ev[e].pending_tasks)
        :: empty(active_tasks[t].waiting_for)
         -> break
         od;
        active_tasks[t].state = RUNNING
       :: else
       fi
     :: empty(pending) -> break
     od
   }
  }

     Sprawdzenie zgodności wartości w bazie danych

  #define db_query(p)
    db[p.name] == p.value

     Zadania

   Sprawdzenie czy nie będzie konfliktów (przed blokowaniem właściwości)

 inline fail_if_incompatible_property(p,err) {
   if
   :: (locks[p.name].value != undef_value &
       locks[p.name].value != p.value) -> err = 1
   :: else
   fi
   } 
 }

   Blokowanie właściwości

 inline snarf_property_lock(this,p,err) {
   atomic{
     fail_if_incompatible_property(p,err);
     append(this,locks[p.name].sub);
     if
     :: locks[p.name].value == undef_value ->
        locks[p.name].value = p.value;
        locks[p.name].achieved = db_query(p)
     :: else
     fi;
     signal_event(SNARF_EVENT)
   }
 }

   Odnajdywanie właściciela

 inline find_owner(p,owner) {
  locks[p.name].sub?<owner>
  }

   Blokowanie nie-właścicieli, aż do momentu wykonania

 inline achieve_lock_property(this,p,err) {
  TaskId owner;
  find_owner(p,owner);
  if
  :: owner == this -> achieve(p,err);
     locks[p.name].achieved = true
  :: else -> wait_for_event(this,MEMORY_EVENT,p);
  fi
 }

   Wykonanie

 inline achieve(p,err) {
  if
  :: db_query(p)
  :: else ->
     if
     :: db[p.name] = p. value
     :: err = 1
     fi
  fi
 }

   Powrót po zmianie wartości w BD

 inline closure() {
  if :: true -> skip :: true -> hang fi
 }

   Zwolnienie blokad

 inline release_lock(this,p) {
  atomic{
    remove(this,locks[p.name].sub);
    if
    :: empty(locks[p.name].sub) ->
       locks[p.name].value = undef_value
    :: nempty(locks[p.name].sub)
    fi
  }
 }

   Wykonanie zadania

 inline execute_task(this,p) {
  bool err = 0;
  {
    snarf_property_lock(this,p,err);
    achieve_lock_property(this,p,err);
    closure()
  }
    unless
  {err || active_tasks[this].state == ABORTED};
  active_tasks[this].state = TERMINATED;
  {release_lock(this,p)}
    unless
  {active_tasks[this].state == ABORTED}
 };

 proctype Achieving Task(TaskId this)
  { Property p;
    p.name = 0;
    if
    :: this ==1 -> p value = 1;
    :: this ==2 -> p value = 2
    fi;
    execute task(this p);
  };

     Demon

 inline interrupt_task(t) {
   active tasks[t].state = ABORTED
 }

 inline property_violated(pn,violation) {
   atomic{
     violation =
      (locks[pn].value != undef_value &
       locks[pn].achieved &
       db[pn] != locks[pn] .value)
   }
 }

 inline check_locks(lock_violation) {
   Property_Name pn;
   list sub = [NO_TASKS] of TaskId;
   TaskId t;
   pn = 0;
   do
   :: pn < NO_PROPS ->
      property_violated(pn,lock_violation);
      if
      :: lock_violation -> atomiccopy(locks[pn].sub,sub)};
         do
         :: sub?t -> interrupt_task(t);
         :: empty(sub) -> break
         od
      :: else
      fi;
      pn++
   :: else -> break
   od;
   pn = 0;
   do
   :: pn < NO_PROPS ->
      property_violated(pn,lock_violation);
      if
      :: lock_violation -> break
      :: else
      fi;
      pn++
   :: else -> break
   od
 }

 proctype Daemon(TaskId this) {
   bit lock_violation;
   byte event_count = 0;
   bit first_time = true;
   do
   :: check_locks(lock_violation);
      if
      :: lock_violation -> do_automatic_recovery()
      :: else
      fi;
      if
      :: (!first_time &&
          Ev[MEMORY_EVENT].count +
          Ev[SNARF_EVENT].count != event_count )
            ->
            event_count =
              Ev[MEMORY_EVENT].count +
              Ev[SNARF_EVENT].count
      :: else ->
         first_time = false;
         wait_for_events(this, MEMORY_EVENT,SNARF_EVENT)
      fi
   od
 };
 

     Środowisko

 proctype Environment()
 { atomic{
     db[0] = 0;
     signal_event(MEMORY_EVENT)
   }
 }
 

     Inicjalizacja

 #define spawn(task,t)
    atomic{
      active_tasks[t].state = RUNNING;
      run task(t)
    }

 init
 {
   spawn(Daemon,0);
   daemon_ready == true;
   spawn(Achieving_Task,1);
   spawn(Achieving Task,2);
   run Environment()
 }