オブジェクト内並列動作

Object REXXの大きな利点の一つに、オブジェクト内での並列動作がある。オブジェクト間の並列動作(異なったオブジェクトのメソッドが複数並行して動作すること)に加え、オブジェクト内並列動作が許されることで、一つのオブジェクトに属する複数のメッセージを同時に処理することができる。例えば、起動後、特定の条件が満たされるまで待機し、条件が満たされると共に実行を開始するようなメッセージを発行することができる。Object REXXは、並列動作をGUARD命令またはメソッドのGUARDED/UNGUARDED属性で制御する。

Object REXXのデフォルトはguarded(保護状態)であり、一つのオブジェクトのメソッドで同時に実行できるのは一つだけである。異なるオブジェクトのメソッドは、GUARD/UNGUARDに影響されず、常に並列動作が可能である。UNGUARDED(保護されない)と指定されたメソッドは、同じオブジェクトの他のメソッドと同時に動作できる。

保護状態の例である:


/* GUARD1.CMD: show guarded method execution */
myObj = .Repeater‾New
myObj‾Repeat(5, "A")
myObj‾Repeat(5, "B")
Exit

::CLASS Repeater
::METHOD Repeat
  Use Arg Count, Message
  Say "Starting output of message:" Message
  Reply /* return to caller immediately 呼び側に直ぐ戻る*/
  Do Count
    Say Message
    Call SysSleep 1
  End
GUARD1.CMDの出力は次のようになろう:

Starting output of message: A
A
A
A
A
A
Starting output of message: B
B
B
B
B
B
どちらのメソッドも起動直後にREPLY命令を発行して即座に戻る。ところが片方の実行が終わるまで、もう一方は実行されない。呼び側に実行を戻してしまう(オプションとして返り値を返せる)RETURN命令と異なり、REPLY命令は呼び側に結果を返すが、その後も別スレッドで実行を続ける。オブジェクトの変数プールは同時には一つの保護されたメソッドからしかアクセスすることができないので、保護されている(デフォルトでは全て保護されている)REPEATメソッドは、オブジェクトの変数プールに完全にアクセスできないと実行できない。それで最初のメソッドの実行が完全に終わって初めて、第二のメソッドが実行可能になる。

同じプログラムに変更を加え、REPEATメソッドを非保護にしよう。実行結果は前のとは異なっているはずである:


/* GUARD2.CMD: show unguarded method execution */
myObj = .Repeater‾New
myObj‾Repeat(5, "A")
myObj‾Repeat(5, "B")
Exit

::CLASS Repeater
::METHOD Repeat UNGUARDED
  Use Arg Count, Message
  Say "Starting output of message:" Message
  Reply /* return to caller */
  Do Count
    Say Message
    Call SysSleep 1
  End
GUARD2.CMDの出力例である:

Starting output of message: A
Starting output of message: B
A
B
B
A
A
B
B
A
A
B
異なったメッセージが切り替わりながら混ざって現れる(正確な順序は既に決定不能である。上のは単なる例である)。

この例から既にマルチスレッドの感触を得られただろう。マルチスレッドは普通、2つのメッセージをまぜこぜに表示するために使うものではなく、制御のために使う。何かの条件が満たされたら、即座に別のスレッドで何かの動作を起こすのである。別スレッドで条件を待つ例を示す:


/* GUARD3.CMD: demonstrate GUARD OFF WHEN instruction */
myObj = .Waiter‾New
myObj‾Increment
myObj‾Wait
Exit

::CLASS Waiter
::METHOD Increment
  Expose Counter
  Counter = 0
  Say "Start counting"
  Reply
  Do Counter = 1 To 100000
    If Counter // 10000 = 0 Then
      Say "Counter is at" Counter
  End

::METHOD Wait UNGUARDED
  Expose Counter
  Say "Waiting for Counter to exceed 50000"
  Guard Off When Counter > 50000
  Say "Counter exceeded 50000 and has a value of" Counter
これは次のような結果をもたらすだろう:

Start counting
Waiting for Counter to exceed 50000
Counter is at 10000
Counter is at 20000
Counter is at 30000
Counter is at 40000
Counter is at 50000
Counter exceeded 50000 and has a value of 50919
Counter is at 60000
Counter is at 70000
Counter is at 80000
Counter is at 90000
Counter is at 100000
プログラムが起動すると、INCREMENTメソッドが実行される。このメソッドはカウンタを0に戻しメインプログラムに戻る。その後、メソッドは単純なループで計数を行い、10000の倍数に達するごとに進行状況を表示する。第2のスレッドでWAITメソッドが実行され、'Waiting for Counter to exceed 50000'(「カウンタが50000を越えるのを待っています」)と表示し、実行を再開するための保護条件(カウンタが50000を越えること)を設定する。この出力から、ちょっとした不都合もわかるだろう。パフォーマンスを上げるために、条件は全ての命令毎にはチェックされない。そこで極めて高速に変化する変数を厳密にチェックしようとするとうまくいかないことがある。
[ Previous page | Next page | Tutorial Index | ]