Action Interval と Parallelism を実現するために, sclient2 はPOSIXスレッド(pthread)を使用する.
プログラムの重要な部分は MyPlayer::run() にある.以下にソースコー ドの一部を示す:
//----------------------------------------
// fork sensor thread
forkSensor() ;
//----------------------------------------
// main loop
while(True) {
if (!isBallSeenRecently(10)) {
//------------------------------
// if ball is not seen recently
// look around by (turn 60)
for(UInt i = 0 ; i < 6 ; i++) {
turn(60) ;
}
} else if (kickable()) {
...
}
}
``forkSensor() ;''ステートメントはセンサ情報を受信、解析するための
新しいスレッドを起動する.
(センサスレッドの動作は "SimpleClient.*" と
"ThreadedClient.*" で定義されている.)
次に,メインスレッドは``chasing the ball and kick to the goal''
の行動列をを生成するメインループへ入る.
Sensing関数はセンサスレッドで並列に扱われるため,メインスレッド
がセンサ入力を扱う必要は無い.
行動の間隔を100msに保つために,sclient2 は ThreadedPlayer::sendCommandPre() という関数によって次のシミュレー ションステップまで待機する. この関数は "ThreadedPlayer.cc" で以下のように定義されている:
Bool ThreadedPlayer::sendCommandPre(Bool bodyp) {
cvSend.lock() ;
if(bodyp) {
while(nextSendBodyTime.isFuture())
cvSend.waitUntil(nextSendBodyTime) ;
}
while(nextSendTime.isFuture()) {
cvSend.waitUntil(nextSendTime) ;
}
return True ;
} ;
この関数では,MutexCondVar cvSend は,上記sclient1 における
select() のタイムアウトと似た機能を提供する.
(MutexCondVarは状態変数(pthread_cond_t) と mutex
(pthread_mutex_)の組合せであり, "itk/MutexCondVar.h" で
定義されている.)
関数はプレイヤがサーバへコマンドを送信する直前に呼び出され,また,
nextSendBodyTime は次のシミュレーションステップのタイムスタンプを
示すので,スレッドは次のticにコマンドを送信するために待機する.