CTaskクラスと非細分型スレッド
これまで私が目にしたスレッドプログラミングの例の多くは、スレッド処理用のデータをグローバル変数に格納し、ミューテックスで保護するという形でした。データを操作する処理はスレッド関数に組み込まれています。私は、そのような形のスレッド処理を、「細分型非同期スレッド処理(SAT:Specialized Asynchronous Threading)」と呼んでいます。
しかし実際には、データとその処理機能は同じオブジェクトにカプセル化されているのが理想です。私は、そのような形のスレッド処理を、「均一型非同期スレッド処理(HAT:Homogeneous Asynchronous Threading)」と呼んでいます。HATでは、各スレッドは細分化されていません。たとえば、HATのソリューションでは、印刷スレッド、I/Oスレッド、という分類はありません。代わりに、単一のスレッドで両方の種類のタスクに対応できます。タスクは、すべてを完備したオブジェクトとして実装されている(つまり、データ自体とその処理に必要な機能の両方がひとまとまりになっている)からです。CTaskクラスは、HATベースのスレッド処理を扱いやすくするための基本クラスです。
typedef enum { TaskStatusNotSubmitted, TaskStatusWaitingOnQueue, TaskStatusBeingProcessed, TaskStatusCompleted } TaskStatus_t; class CTask { private: CMutexClass m_mutex; TaskStatus_t m_state; ThreadId_t m_dwThread; public: void SetTaskStatus(TaskStatus_t state) { m_mutex.Lock(); m_state=state; m_mutex.Unlock(); } void SetId(ThreadId_t *pid) { memcpy(&m_dwThread,pid,sizeof(ThreadId_t)); } /** * * Wait * waits for up to timeoutSeconds for a task * to complete * **/ BOOL Wait(int timeoutSeconds) { timeoutSeconds = timeoutSeconds * 1000; if( Status() != TaskStatusCompleted && timeoutSeconds > 0 ) { Sleep(100); timeoutSeconds = timeoutSeconds - 100; } if( Status() == TaskStatusCompleted ) return TRUE; return FALSE; } /** * * Where * returns current state of a task * **/ TaskStatus_t Status() { TaskStatus_t state ; m_mutex.Lock(); state = m_state; m_mutex.Unlock(); return state; } void Thread(ThreadId_t *pId) { memcpy(pId,&m_dwThread,sizeof(ThreadId_t)); } CTask(){m_state=TaskStatusNotSubmitted; memset(&m_dwThread,sizeof(ThreadId_t),0); } ~CTask(){} virtual BOOL Task()=0; };
| 関数 | 説明 |
| m_mutex | オブジェクト同期用のミューテックスオブジェクト |
| virtual BOOL Task() | タスクを実行するためにCThreadオブジェクトから呼び出される |
| TaskStatus_t Status() | タスクの状態(TaskStatusNotSubmitted、TaskStatusWaitingOnQueue、TaskStatusBeingProcessed、TaskStatusCompleted)を判断する |
| void Thread(ThreadId_t *pid) | 処理しているスレッドのスレッドIDを返す |
| BOOL Wait(int iTimeInSeconds) | タスクが完了するかiTimeInSecondsが経過するまで、呼び出し元のスレッドを待ち状態にする。iTimeInSeconds内にタスクが完了しない場合はFALSEが返る。それ以外の場合はTRUEが返る |
CThreadクラスをまだ定義していませんが、CThreadオブジェクトとCTaskオブジェクトがどのように連係するかは、定義がなくても理解できます。これら2つのオブジェクト型の連係の概要を次に示します。
CTaskオブジェクトの処理手順
- CTaskオブジェクトが処理のためにCThreadオブジェクトに渡される
- CThreadオブジェクトがCTaskオブジェクトを先着順(FVFS:First Come First Served)方式のキューに格納する
- CThreadオブジェクトがCTaskオブジェクトの状態をTaskStatusWaitingOnQueueに設定する
- CThreadオブジェクトが待機キューからCTaskオブジェクトをポップする
- CThreadオブジェクトがCTaskオブジェクトの状態をTaskStatusBeingProcessedに変更する
- CThreadオブジェクトがCTaskオブジェクトのメンバ関数taskを呼び出してタスクを実行する
- CThreadオブジェクトがCTaskオブジェクトの状態をTaskStateCompletedに変更する
