Microsoft DirectX 8.0 (C++)

DirectPlay のネットワーキング コールバック

Microsoft® DirectPlay® のネットワーキング コールバック関数は、PFNDPNMESSAGEHANDLER 型である。ネットワーキング セッションの種類に応じて、IDirectPlay8Peer::InitializeIDirectPlay8Client::Initialize、または IDirectPlay8Server::Initialize を使ってコールバック関数のアドレスを登録する。

同期に関する問題

DirectPlay コールバックでの処理中にゲーム データの整合性を保つためには、3 つのスレッド同期オブジェクトのいずれかを採用する必要がある。

ゲーム データがどのように破損するかを説明するため、コールバックで構造体にゲーム データのパケットを挿入する場合について考える。1 番目のコールバックが完了しないうちに、ほかのスレッドからコールバックが再帰的に実行されると、このスレッドも、メモリ内の同じ場所にある構造体にアクセスし、内容を変更しようとする可能性がある。この結果、1 番目のスレッドが構造体に置いたデータが、2 番目のスレッドが構造体に置いたデータで上書きされる。これはマルチスレッドのごく簡単な例であり、スレッドが正常に同期しなくなる原因はほかにもいろいろあるので、注意が必要である。また、自作を試みる前に、マルチスレッド コールバックの実装に関する高度な知識を身に付けることも重要である。

DirectPlay ネットワーキング セッションでデータを同期させる方法の例については、「クリティカル セクション オブジェクトを使った DirectPlay ネットワーキング コールバックの実装」を参照すること。

ワーカー スレッド

"ワーカー スレッド" を自作するのも 1 つの方法である。ワーカー スレッドは、アプリケーションで定義されるもう 1 つのマルチスレッド コールバックであり、DirectPlay コールバックと関係なくゲーム データを処理するために作成される。この目的を達成するために、最も一般的な手段として、DirectPlay のネットワーキング コールバック スレッドでは、受け取ったデータをバッファに保存する。次に、新しいスレッドが作成され、バッファリング データを処理するように知らせるメッセージがワーカー スレッド コールバックに送信される。

マルチスレッドのパフォーマンスに関する問題と非同期処理

DirectPlay コールバック内でメッセージの処理にかける時間は、慎重に検討する必要がある。DirectPlay コールバック内で大量のデータを処理し、データをロックするメカニズムを使ってスレッドの同期をとると、ほかのスレッドがコールバックを実行するために待機するときにブロック問題が起きる。

一方、ワーカー スレッドを実装し、ゲーム データの処理を別のコールバックに任せると、自作のスレッドと DirectPlay で作成されたスレッドの間で CPU がコンテキストを切り替えるため、オーバーヘッドが大幅に増える危険性がある。この方法を採用できるのは、ゲーム データの処理に非常に時間がかかり、ゲームのリアルタイム処理にとって欠かせないデータでない場合に限られる。たとえば、プレーヤーの位置データは、ゲーム内でプレーヤーをリアルタイムに配置するために欠かせないデータなので、ワーカー スレッドで処理することは推奨されない。

コールバックから DPNSUCCESS_PENDING を返し、データ バッファへのポインタを作成し、ワーカー スレッドがそのポインタを利用できるようにすることもできる。ワーカー スレッドは、ゲーム データを処理し終わると、使用しているトポロジに応じて IDirectPlay8Peer または IDirectPlay8Client の ReturnBuffer メソッドを呼び出す。