スレッドをカプセル化するためのクラス
スレッドをカプセル化するためのクラス.ThreadJack では,複数のスレッドを並行動作させることができる. このクラスはスレッドの作成・消去やスレッドに対する操作をカプセル化している.
ThreadJack では, スレッドによって実行されるプログラムの実装方法には, 以下の 2つがある.
1. TJThread をサブクラス化し,run() をオーバーライドする.
2. TJRunnable をサブクラス化し,run() をオーバーライドする.
それぞれの実行方法は,次の通り. いずれの場合も TJThread またはそのサブクラスのオブジェクトが必要である.
* (1) TJThread のサブクラスのオブジェクトを作成 * * class MyThread : public TJThread { * ・・・・ * public: * MyThread(const char* name) : TJThread(name) { } * ・・・・ * void run() { * ・・・・ // override TJThread::run() * } * }; * * MyThread* thread = new MyThread("myname"); * thread->start(); * ......... * thread->join(); // 必要であれば終了待ち合わせ * // スレッドオブジェクトは delete してはならない * * (2) TJRunnable の実装クラスのオブジェクトを引数にして * TJThread オブジェクトを作成 * * class MyRunnable : public TJRunnable { * ・・・・ * public: * ・・・・ * void run() { * ・・・・ // implement TJRunnable::run() * } * }; * * MyRunnable* runnable = new MyRunnable; * TJThread* thread = new TJThread(runnable, "myname"); * thread->start(); * ......... * thread->join(); // 必要であれば終了待ち合わせ * // スレッドオブジェクトは delete してはならない * *(2)の使用法は,1つの TJRunnable オブジェクトを複数の TJThread オブジェクト で共用できる,という利点がある.
TJThread は java.lang.Thread に似ているが java とはメモリ管理方法 が異なるためスレッドオブジェクトの作成と消去に次の注意が必要になる.
* ◆スレッドオブジェクトは必ず new 演算子によりヒープ領域に確保すること. * ◆スレッドオブジェクトはアプリケーションが delete しないこと. *あるスレッドが新たに別のスレッドを生成した場合, 生成元のスレッドを親スレッド,生成されたスレッドを子スレッドと呼ぶ.
[スレッドの状態とシステムの終了]
ANSI/ISO C++ により規定される int main() というエントリポイント に最初に入るスレッドを, 特に「main スレッド」と呼び,アプリケーション が TJThread クラスのインスタンスとして生成したスレッドと必要に応じて 区別することがある.
main スレッド以外のスレッドでは,スレッドの実行プログラムは TJThread もしくは TJRunnable の run() メソッドの実装として表現される.
スレッドが run() を実行中の時,そのスレッドは alive であるという. run() から復帰するか,または明示的に TJThread::exit(int) をよびだすこと で run() は終了し,alive 状態から非 alive 状態へと遷移する. スレッドの終了コードは,run() から自然に復帰した場合は0 となり, TJThread::exit(int) を呼び出した場合は引数が終了コードとなる. この終了コードは他のスレッドが TJThread::join で受け取ることができる.
main スレッドも,TJThread::exit(int) を呼び出すことができる.この場合も main スレッドが非 alive 状態となる.
ThreadJack に於けるシステム(プロセス)の終了は,次のどれかが起こった 時である.
* * 1. main スレッドが main からの復帰(return)した時. * (ただしTJThread::exit()呼び出しは復帰と見なさない) * 2. あるスレッド(main 以外でもよい)が大域のシステム終了(プロセス終了) * を引き起こす呼び出し(ANSI/ISO C++ では ::exit() もしくは ::abort()) * を呼び出した時. * 3. 全スレッドが非 alive となった時. * *また,ThreadJack では プロセスのコピーを行うシステム動作 (UNIX の fork, Win32 の CreateProcess)に対しての動作は未定義である. (将来の拡張項目とする)
[プライオリティ]
すべてのスレッドはプライオリティを持つ.一般に, プライオリティの高い スレッドはプライオリティの低いスレッドに優先して実行される. ただし,プライオリティがスケジューリングに与える正確な影響は システム依存である.
プライオリティの数値は Java と同じ仕様とする.プライオリティは そのスレッドを生成したスレッドから継承され setPriority() により 変更できる.
プライオリティは,スレッドの親子関係の中で継承される.すなわち, 新たに生成されたスレッドのプライオリティの初期値は親スレッドの プライオリティと同じ値である.
[待ち合わせ性]
スレッドオブジェクトに対するjoin()の呼び出しによって,他のスレッド がその終了を待ち合わせることができる. この性質を待ち合わせ性(joinability)という. しかし,作成したスレッドの終了に関心がない場合,意識的に待ち合わせ を省略することも可能である.
* (a) 作成したスレッドの終了に関心がある場合 * MyThread* t = new MyThread("myname"); * t->start(); // joinable なスレッド * ・・・ * int exitcode = t->join(); * * (b) 作成したスレッドの終了に関心がない場合 * FreeThread* t = new FreeThread("myname"); * t->setJoinable(false); // 非 joinable なスレッド * t->start(); * // これ以降,t の実行状態はこのスレッドから切り離される. * // [警告] これ以後の *t のアクセスは一般に危険 *ここで (a) では作成されたスレッドが終了したとき join() が復帰し戻り値に exit() の引数が返される. それに対して (b) では作成されたスレッドとの関わ り合いは一切ない. 作成したスレッドの終了状態や終了のタイミングを知る必要 がない場合にはこの方法は都合がよい.ただし,joinable なスレッドは必ず join する必要があり,逆に 非 joinable なスレッドは決して join してはいけない.
新規作成されたスレッドの待ち合わせ性は必ず joinable であり, 待ち合わせ性 は子スレッドに継承されることはない. setJoinable(false) の操作を受けたスレッドだけが 非joinable となる. 非 joinable スレッドを join() した場合の動作は不定である. joinable か どうかは setJoinable(bool) により変更可能であるが main スレッドだけは変更 できず, 必ず非 joinable である.
待ち合わせ性は,java.lang.Thread の Deamon 性とは無関係の属性であること に注意.
[その他]
スレッドは名前を持つ.名前は必ずしも全スレッドを通して一意ではない. 名前を指定せずに生成したスレッドには,適当な名前が付与される.
java.lang.Thread は java.lang.Runnable を implements しているが, ThreadJack では2つのクラスTJThread と TJRunnable には継承関係を 持たせていない.
TJThread のサブクラスを作る場合,そのクラスのデストラクタを protected と することを推奨する. これにより,スレッドを自動変数として生成したり, delete を直接呼び出すといったバグをコンパイル時に発見できる.
カレントスレッド以外のスレッドを強制終了させる機能(いわゆるキャンセル)は 提供しない. これを提供するとプログラマはキャンセルからの保護を検討しなけ ればならなくなる. java.lang.Thread の suspend, stop, resume は提供しない.
スレッドクラスのオブジェクトを扱う場合,特に this オブジェクトに対する 操作とカレントスレッドに対する操作の混乱が起こりやすいので注意が必要である. このクラスの主な public メソッドは以下のように分類される.
* [A] インスタンスメソッド -- this オブジェクトに対する操作 * void setPriority(int) * int getPriority() * void setJoinable(bool) * bool isJoinable() * bool isAlive() * void setName(const char*) * const char* getName() * TJThread::ID getThreadID() * [B] クラスメソッド -- クラス全体の操作 * TJThread* getThread(TJThread::ID) * int activeCount() * [C] カレントスレッドに対する操作 * void exit(int) * void sleep(long) * void yield() * TJThread::ID currentThreadID() * TJThread* currentThread() * const char* currentThreadName() * [D] 親スレッドの立場での子スレッドに対する操作 * TJThread( ... ) * void start() * int join() * int join(long) * [E] 通常はユーザが直接呼び出すことの無い操作 * void run() *特に注意すべき点は [C] のカレントスレッドに対する操作である. これらは すべて static であるため形式的にはクラスメソッドであるがカレントスレッド という特定のスレッドに対する操作である.
スレッドの識別情報としてスレッド識別子(ID)とスレッドオブジェクトへの ポインタが考えられる. 前者は効率的に実装できるが,後者のは一般に 内部的なクラスロックを必要とするため, 非効率である. したがってスレッドの識別のみ必要ならスレッド識別子を使うべきである.
意味 -- 非 joinable なスレッドを join() しようとした.
JOINABLE ではないスレッドを join() した場合の動作は不定である.
もしタイミングにより暴走をまぬがれた場合はこの値が戻される.
この値は便宜上のものであり,アプリケーションはこの値を使った
コードを書いてはならない.
値は,INT_MAX
意味 -- タイムアウト値指定の join() でタイムアウトした.
値は,INT_MAX-1
TJThread のサブクラスでもデストラクタを protected にすること
を推奨する.(スレッドオブジェクトのスタック上に確保や,
delete 呼び出しの禁止)
このメソッドはライブラリが呼び出すスレッドのエントリポイントで
あり, ユーザが呼び出すことは無意味である.
TJThread::exit によって返されるコードを受け取ることができる.
joinable ではないスレッドに対して join() を実行した場合の動作
は不定である.
TJThread::exit によって返されるコードを受け取ることができる.
ただしスレッド名の一意性はこのメソッドでは保証されない.
このデータはスレッド毎に保持できる.
通常はスタックがあればスレッドごとの情報を記憶できるがスタックで
はメソッドから復帰すると消滅する.
スレッドごとに, かつメソッドから復帰しても保存されるデータを管理
したい場合にこの機能が使える.
管理されるデータの寿命についてはアプリケーションの責任である.
static const ID None
static const int JOINDETACHED
static const int JOINTIMEOUT
static const int MIN_PRIORITY
static const int MAX_PRIORITY
static const unsigned DEFSTACKSIZE
enum Kind
TJThread(unsigned stacksize = DEFSTACKSIZE)
TJThread(const char* name, unsigned stacksize = DEFSTACKSIZE)
stacksize - スタックサイズ TJThread(TJRunnable* target, unsigned stacksize = DEFSTACKSIZE)
stacksize - スタックサイズ TJThread(TJRunnable* target, const char* name, unsigned stacksize = DEFSTACKSIZE)
name - スレッド名
stacksize - スタックサイズvirtual ~TJThread()
void setPriority(int pri)
int getPriority() const
virtual void setJoinable(bool on)
virtual bool isJoinable() const
virtual void start()
virtual void run()
int join()
int join(long milliseconds)
static void exit(int code)
static void sleep(long milliseconds)
static void yield()
void setName(const char* name)
const char* getName() const
bool isAlive() const
static int activeCount()
virtual ID getThreadID() const
static TJThread* getThread(ID tid)
static ID currentThreadID()
static TJThread* currentThread()
static const char* currentThreadName()
() void putData(void* anydata)
索引(アルファベット順) HTMLクラス継承 または Java