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にコマンドを送信するために待機する.