3

私は次のpromelaコードを持っています:

chan level = [0] of {int};

proctype Sensor (chan levelChan) {
    int x;
    do
    :: true ->
            levelChan ? x;
            if 
            :: (x < 2) -> printf("low %d", x);
            :: (x > 8) -> printf("high %d", x);
            :: else -> printf("normal %d", x);
            fi
    od
}

init {
    run Sensor(level);  
    int lvl = 5;
    level ! lvl;
    lvl = 0;
    do 
    :: true ->
        level ! lvl; 
        lvl++;
        (lvl > 9) -> break;
    od
}

レベル (0-9) 情報をチャネルに送信し、このレベルに応じてセンサー出力を low|normal|high にすることを期待しています。とてもシンプルです。しかし、なぜ SPIN はいつもタイムアウトを言っているのでしょうか?

  0:    proc  - (:root:) creates proc  0 (:init:)
Starting Sensor with pid 1
  1:    proc  0 (:init:) creates proc  1 (Sensor)
  1:    proc  0 (:init:) 1.pml:18 (state 1) [(run Sensor(level))]
  2:    proc  1 (Sensor) 1.pml:6 (state 11) [(1)]
  3:    proc  0 (:init:) 1.pml:20 (state 2) [lvl = 5]
  4:    proc  0 (:init:) 1.pml:20 (state 3) [level!lvl]
  4:    proc  1 (Sensor) 1.pml:8 (state 2)  [levelChan?x]
  5:    proc  1 (Sensor) 1.pml:9 (state 9)  [else]
  6:    proc  0 (:init:) 1.pml:21 (state 4) [lvl = 0]
normal 5  8:    proc  1 (Sensor) 1.pml:12 (state 8) [printf('normal %d',x)]
  9:    proc  0 (:init:) 1.pml:22 (state 10)    [(1)]
 12:    proc  1 (Sensor) 1.pml:6 (state 11) [(1)]
 13:    proc  0 (:init:) 1.pml:24 (state 6) [level!lvl]
 13:    proc  1 (Sensor) 1.pml:8 (state 2)  [levelChan?x]
 14:    proc  1 (Sensor) 1.pml:9 (state 9)  [((x<2))]
low 0 15:   proc  1 (Sensor) 1.pml:10 (state 4) [printf('low %d',x)]
 17:    proc  0 (:init:) 1.pml:25 (state 7) [lvl = (lvl+1)]
 19:    proc  1 (Sensor) 1.pml:6 (state 11) [(1)]
timeout
#processes: 2
 19:    proc  1 (Sensor) 1.pml:8 (state 2)
 19:    proc  0 (:init:) 1.pml:26 (state 8)
2 processes created

do ループの反復を 1 回しか実行していないように見えるのはなぜですか?

4

1 に答える 1

3

initプロセスの do ループ内のステートメントは順番に実行されます。

do 
:: true ->
    level ! lvl; 
    lvl++;
    (lvl > 9) -> break;
od

do ループが最初に実行されると、チャネルをlvl介して送信され、 が増加し(現在は 1)、テストされます。これは false であるため、ブロックされ、タイムアウトが発生します。levellvl(lvl > 9)

::do ループに複数のオプションを含めるには、各オプションの開始を定義する必要があります。

do
 :: true ->
    level ! lvl; 
    lvl++;
 :: (lvl > 9) -> break;
od

ただし、これでも期待どおりのパフォーマンスは得られません。lvlが 9 より大きい場合、do ループの両方のオプションが有効で、どちらか一方を選択できます。そのため、チャネルを介して を送信し続けて を増やすことを選択できる場合、ループは必ずしも壊れませlvl > 9ん。lvllevellvl

最初の do オプションと 2 番目の do オプションに条件を設定する必要があります。

do 
:: (lvl <= 9) ->
    level ! lvl; 
    lvl++;
:: (lvl > 9) -> break;
od

この例では、for ループ構文を使用する方がよい場合があります。

init {
  run Sensor(level);  
  int lvl = 5;
  level ! lvl;

  for (lvl : 0..9){
    level ! lvl; 
  }
}

この例では、Sensorの do ループが原因でタイムアウト エラーが発生することに注意してください。initプロセスが終了しても、チャネルSensorからの読み取りを試みてタイムアウトします。level

于 2013-02-15T18:29:48.443 に答える