ここでは PiaTransport の概念と、内部動作の詳細について説明します。
同一の通信路を利用する通信であっても、多種多様な形態があり、それぞれ性質が異なります(例: UDP, TCP, IP 電話など)。これらの性質の異なる通信を効率よく行うために、Pia では目的に応じたプロトコル(Pia プロトコル)を用意しています。
Pia プロトコルの基底クラスとして transport::Protocol が用意され、各種通信の性質に応じて派生クラスが用意されています(例: transport::UnreliableProtocol, transport::ReliableProtocol, chat::VoiceProtocol)。
アプリケーションがステーション間で通信を行う際は、目的の応じた Pia プロトコルのインスタンスを作成し、そのインスタンスの送受信 API を呼び出すことになります。
PiaTransport をセットアップすると、送信スレッドと受信スレッドが作成されます。これらの送受信スレッドと、アプリケーションスレッドが呼びだす各プロトコルの送受信 API との関係を図示します。
送信側の動作を簡単に説明すると、以下のようになります。
同様に受信側の動作を簡単に説明すると、以下のようになります。
一般に、I/O アクセスの発生する API 呼び出しは長時間ブロックする傾向にありますが、前述したとおり、PiaTransport では送受信スレッドが SDK の送受信 API を呼び出します。 そのため、アプリケーションスレッドが SDK の送受信 API 呼び出しでブロックすることはありません。
上記は簡略化した解説でした。ここでは PiaTransport におけるディスパッチ関数と送受信処理、送受信スレッドの詳細を説明します。
PiaTransport には、以下の処理を担当するディスパッチ関数が用意されています。
このディスパッチ関数は、nn::pia::common::Scheduler::Dispatch() から暗黙的に呼び出されます。ディスパッチ処理が定期的に実行されないと、Pia は正常に動作できませんので、アプリケーションは nn::pia::common::Scheduler::Dispatch() を毎フレーム 1 ~ 2 回の間隔で定期的に呼び出す必要があります。
送信処理は以下のように行われます。
対応する受信処理は以下のように行われます。
送受信スレッドの動作を以下の擬似コードで示します。
while(true)
{ if(isSendPacketExist()) { // 送信対象のパケットが残っていれば、連続して send() を実行します。 send(packet); } else { // 送信対象のパケットが無くなると、送信スレッドはスリープします。 sleep(sendThreadSleepSpan); } } |
while(true)
{ if(isReceivePacketExist()) { // 受信対象のパケットが残っていれば、連続して receive() を実行します。 receive(&packet); } else { // 受信対象のパケットが無くなると、受信スレッドはスリープします。 sleep(receiveThreadSleepSpan); } } |
送受信スレッドには比較的高い優先度が与えられ、定期的にパケットの送受信を行います。 この送受信によってスレッドはブロックし、より優先度の低いスレッド(メインスレッド等)に実行権が移されます。 また、送受信対象のパケットが無くなると、送受信スレッドはスリープし、スレッドの実行権が譲られます。
送受信スレッドのスリープ間隔は transport::ThreadStreamManager::SetSendThreadSleepTimeSpan() と transport::ThreadStreamManager::SetReceiveThreadSleepTimeSpan() で指定することもできます。スリープ間隔を短くすると、データが滞留する時間が短縮され、プログラム動作のレスポンスが向上する可能性があります。ただし、スレッドスイッチが頻繁に発生することで、全体的な CPU 負荷は上昇する可能性があります。
Pia 送受信スレッドへの CPU 割り当てが滞った場合、Pia のシステム処理に悪影響が出る可能性があります。
送受信スレッドの優先度はアプリケーションが指定することもできますが、通常、送受信スレッドの優先度はアプリケーションが Pia API を呼び出すスレッドの優先度よりも高くします。アプリケーションが Pia 送受信スレッドよりも高い優先度のスレッドを作成するなどした場合は、そのスレッドが長時間 CPU を独占しないように注意が必要です。