このチュートリアルでは、チュートリアル6の項目を拡張して三番目の並列戦略である スレッドプールを実装する。6章で5章の内容を拡張したように、既に作成した部分は そのまま残し、一種の「ボーナス」のようにスレッドプール機能を追加する。 既に見てきた通り、基本オブジェクトについては一部変更があるが、全部ではない。 目標を達成するために、まずスレッドプールのコンセプトを抽象化してくれる オブジェクトについて紹介していく。
ACE_Task について何も知識が無い場合、この章は分かりにくいと思うかもしれない。 その場合のアドバイスとしては、何度も読み返してほしいということくらいだ。 それでも問題が解決しない場合には、$ACE_ROOT/tests の ACE_Task に関するテストか $ACE_ROOT/examples のサンプルを参照してもらいたい。
Kirthikaによる概略:
ACE_Task はアクティブオブジェクトパターンに沿っている。そのため、タスク オブジェクトのメソッド実行を新しいスレッドによって行える。つまり、メソッドの 実行を、その呼び出しと切り離すことができる。ACE_Task は、その下地となる スレッド(もしくはスレッドのプール)と、タスク間の通信を取り持つ Message_Queue で成り立つ。Message_Queue は Message_Block によってできている。
Client_Acceptor はリアクターと共に登録され、接続リクエストを待つ。 何らかの動きがあるとリアクターは Acceptor の handle_input() メソッドを呼ぶ。 (スレッドプール戦略における)Acceptor は Client_Handler によって自分自身を リアクターの登録から外し、スレッドプールの Message_Queue へ登録し直す。 このとき、スレッドプールでは svc() メソッドが handle_input() から呼ばれるのを 待っている。その後、実行用の新スレッド上にてデータの処理が行われる。 ACE_MT_SYNCH オプションは異なる Message_Queue 上の Message_Block (たとえば、 メインスレッドからスレッドプールの一つ)にアクセスすることを容易にする。
thread_pool クラスは ACE_Task クラスから派生される。その svc() メソッドは Message_Queue からスレッドを一つ取り出し、その上で handle_input() を呼ぶ。 これらのスレッドが働いている一方で、アイドル中のスレッドはキューに仕事が 来るまで待機している。その他、プールのアクティブなスレッドカウンターとして ACE_Atomic_OPが利用されているまた、ACE_Guard クラスはスレッドセーフな カウンタインクリメントやスレッドプール中の Message_Block の安全な解放に 役立っている。このクラスはそのスコープに応じてミューテックスロックの作成や 解放を行うことにより、クリティカルセクションへのアクセスを保護している。
付記:スレッドプールの完全な解放には、プール内の各スレッドが終了できるだけの スリープ期間が必要である。
このチュートリアルは、スレッドプール戦略によるサーバの実装の要点と、それに 関する ACE_Task クラスの処理内容についてまとめた。ACE_Task クラスは スレッド生成と実装に関するオブジェクト指向なアプローチを提供する。