マニュアルページ task.3
名前
task - C++ タスクライブラリのコルーチン
形式
#include <task.h>
typedef int (*PFIO)(int,object*);
typedef void (*PFV)();
class object {
public:
// 公開された定数と型
enum objtype { OBJECT, TIMER, TASK, QHEAD, QTAIL, INTHANDLER };
// 公開されたコンストラクタ
object();
// 公開されたデータメンバー
object* o_next;
static PFIO error_fct;
// 公開された仮想関数
virtual objtype o_type();
virtual int pending();
virtual void print(int, int=0);
// 関数の出力時に引数として使用したフラグをプリント
#define CHAIN 1
#define VERBOSE 2
#define STACK 4
// 公開されたその他の関数
void alert();
void forget(task*);
void remember(task*);
// 公開された静的メンバー関数
static int task_error(int, object*);
static task* this_task();
};
class sched: public object {
public:
// 公開された定数と型
enum statetype { IDLE=1, RUNNING=2, TERMINATED=4 };
protected:
// 限定公開コンストラクタ
sched();
public:
// 公開されたデータメンバー
static task* clock_task;
static PFV exit_fct;
// 公開された仮想関数
virtual int pending();
virtual void print(int, int =0);
virtual void setwho(object*);
// 公開されたその他の関数
void cancel(int);
int dont_wait();
sched* get_priority_sched();
int keep_waiting();
statetype rdstate();
long rdtime();
int result();
// 公開された静的メンバー関数
static long get_clock();
static sched* get_run_chain();
static int get_exit_status();
static void set_exit_status(int i);
static void setclock(long);
};
class task: public sched {
public:
// 公開された定数と型
typedef unsigned char _Uchar;
enum modetype { DEDICATED=1, SHARED=2 };
#define DEFAULT_MODE DEDICATED
#define SIZE 3000
protected:
// 限定公開コンストラクタ
task(char* = 0, modetype = DEFAULT_MODE, int = SIZE);
public:
// 公開されたデータメンバー
task* t_next;
_Uchar* t_name;
// 公開された仮想関数
virtual objtype o_type();
virtual void print(int, int =0);
virtual void setwho(object*);
// 公開されたその他の関数
void cancel(int);
void delay(int);
int preempt();
void resultis(int);
void sleep(object* =0);
void wait(object*);
int waitlist(object* ...);
int waitvec(object**);
object* who_alerted_me();
// 公開された静的メンバー関数
static task* get_task_chain();
};
class timer: public sched {
public:
// 公開されたコンストラクタ
timer(int);
// 公開された仮想関数
virtual objtype o_type();
virtual void print(int, int =0);
virtual void setwho(object*);
// 公開されたその他の関数
void reset(int);
};
機能説明
「タスク」は、対応するプログラムを実行する制御スレッドを持つ
オブジェクトです。つまり、ユーザータスクはクラス task から派
生した型のオブジェクトです。そのオブジェクトのコンストラクタ
は、タスクのメインプログラムです。タスクがコンストラクタの終
了後も存続することはありません。
タスクシステムは、直ちに実行できる操作または待機しなければな
らない操作、さらに「動作可能」または「保留中」であるオブジェ
クトに関して機能します。タスクが直ちに実行できるサービスを要
求するか、動作可能なオブジェクトを待機する場合、そのタスクは
処理を続けます。必要なサービスが直ちに実行されないか、操作す
る オ ブジェクトが使用可能でない場合、タスクはブロックされま
す。動作中のタスクがブロックされると、スケジューラは実行可能
な次のタスクを選択し、そのタスクに制御を与えます。タスクが先
取りされることはありません。ただし、あるタスクをブロッ ク し
て、他のタスクを実行できるようにすることがあります。制御は、
ラウンドロビン形式で処理されます (タスクに優先順位を与 え た
り、実行を待機しているタスクのリストの先頭に移動することがで
きます)。オブジェクトが新しく動作可能になるたびに、それを 待
機しているすべてのタスクにそのことが通知され、通知を受けたタ
スクが実行可能になります。
各タスクには、次の 3 つの状態があります。
RUNNING 現在実行中または実行可能。
IDLE 実行不可能。オブジェクトを待機中。
TERMINATED
タスクは終了し、再開不可能。タスクの戻り値 を
取り出すことができます。
タスクシステムは、クラス object にもとづいています。このクラ
スから派生されるすべてのオブジェクトは、キューに登録したり、
タスクに待機させることができます。仮想メンバー関数 pending()
は、 オ ブジェクトが動作可能でない場合にゼロ以外の値を返しま
す。オブジェクトの各型にこの関数の独自のバージョンを用意する
ことができ、それにより、オブジェクトが動作可能か保留中かを決
定する独自の基準を持つことができます。ただし、各型のオブジェ
クトには、そのような関数を 1 つしか定義できません。
各オブジェクトは、それを待機しているオブジェクトのリストであ
る「リメンバ・チェーン」を持っています。タスクが動作可能でな
いオブジェクトを待機していると、そのタスクは中断さ れ (IDLE
状 態)、オブジェクトのリメンバ・チェーンに追加されます。次に
オブジェクトが動作可能 (保留中ではない) になると、メンバー関
数 object::alert() によって、待機している各タスクにそのこと
が通知されます。この関数は、これらのタスクの状態 を RUNNING
状態に変更し、スケジューラの「実行チェーン」である、動作可能
タスクのリストに戻します。
クラス object の派生クラス sched は、タスクのようなオブ ジェ
クトに共通の機能を提供します。スケジューリング関数はこのクラ
スに含まれています。スケジューリング操作はスケジューラとして
独 立しているのではなく、クラス sched の一部分です。各タスク
は他のタスクとともに動作し、そのメンバー関数を用 い て ス ケ
ジュー リ ングを行います。このクラスはインスタンス化できませ
ん。 task と timer の基底クラスとしてしか使用できません。
また、クラス sched は、時間の経過をシミュレートする機能も 提
供します。シミュレートされた時間の単位は実時間と関係がなくて
もかまいません。シミュレートされたシステムクロックはゼロに初
期 化されます。クロックの値は、 sched::setclock() によって一
度だけ設定できます。設定後、クロックは task::delay() の呼 び
出しが行われた場合にだけ進みます。このときのパラメタは、遅延
を示すシミュレートされた単位時間の数です。パラメタで指定され
た 時間が経過すると、 delay() は制御を呼び出し側に返します。
delay() を呼び出すことで、クロックは、遅延時間と、何か物事が
発生するようにスケジュールされている、次のシミュレートされた
時間の早い方に進みます。ク ロッ ク の 現 在 の 値 は、 関 数
sched::getclock() によって読み取ることができます。
クラス timer は、単に指定されたシミュレートされた時間だけ 遅
延 さ せ、終了する、余分な機能をいっさい持たないタスクです。
timer を待機することができ、その時間が経過するとそれを待機し
て いるすべてのタスクに通知されます。 timer は、RUNNING また
は TERMINATED のどちらかの状態にできますが、IDLE にするこ と
はできません。
クラス task は sched の派生クラスで、ユーザータスクの基本 機
能を提供します。 task 型のオブジェクトはインスタンス化できま
せん。すべてのユーザータスクは、クラス task から直接派生され
たものでなければなりません。すなわち、ユーザータスク型から派
生型を作成することはできません。例を示します。
task mytask; // エラー: タスクオブジェクトは作成
できない。
class consumer : public task { ... } // OK
class glutton : public consumer { ... } // エラー: 再度
派生できない。
コンストラクタ task は protected 宣言されているため、最初 の
エラーはコンパイラによって検出され、報告されます。3 行目のエ
ラーは検出されませんが、プログラムは動作しません。
タスクは、コンストラクタを終了するだけでは終了できません。ま
た、関数の戻り値の機能を用いて、タスクから値を返すことはでき
ません。代わりに、タスクの戻り値は task::resultis() ま た は
task::cancel() のどちらかを呼び出すことによって設定しなけれ
ばなりません。そうすれば、タスクは TERMINATED 状態にな り ま
す。あるタスクの戻り値は、他のタスクから task::result() を呼
び出すことで取り出すことができます。この関数は、問い合わせら
れたタスクが終了するまで、呼び出し側タスクを中断します。タス
クは値を返す必要がない場合でも、 resultis() または cancel()
を呼び出し、そのタスクが破棄される前に適切に終了されるように
しなければなりません。
コンストラクタ task は、名前、モード、スタックサイズの 3 つ
の引数 (省略可能) を持ちます。
名前は、動的に割り当てられた文字列かヒープ上の文字列でなけれ
ばならず、ある関数に対してローカルな文字配列を指定することは
できません。名前は出力上にだけ現れ、タスク操作には影響を与え
ません。
モードは、タスクが使用するスタックの種類で、 DEDICATED ( デ
フォルト) または SHARED のどちらかになります。通常、専用のス
タック (DEDICATED) が必要です。すなわち、タスク独自のス タッ
クとしてメモリー領域を確保します。共有スタック (SHARED) は資
源を消費します。これは、タスクが稼働状態になったり非稼働状態
になったりするときに、独自のスタックを共有領域と保存領域との
間でスワップしなければならない場合があるためです。何百という
小規模なタスクがある場合には、共有スタック領域が有効になりま
す。
スタックサイズは、タスクが使用できる最大のスタック領域の量を
指定します。デフォルトは 3000 バイトです。スタック領域がオー
バーフローしたかどうかの確実なテストもなく、スタックを動的に
拡 大 することもできません。タスクがスワップインされると、ス
タックサイズがチェックされ、このときのオーバーフローは致命的
エラーとなります。タスクの実行中に、関数呼び出しのネストが深
いことや、ローカル変数の記憶領域のサイズが大きなことが原因で
スタックがオーバーフローすると、プログラムが異常な動作をした
り、クラッシュすることがあります。
task からクラスを派生すると、そのコンストラクタは、すでに 存
在する他のタスクと同時に動作する新しいタスクとなります。関数
main() は、システムで最初のタスクを作成するタスクに な り ま
す。 main() の中でいくつかのタスクが順に起動する場合、最初の
タスクがブロックされ、 main() が新しいタスクを作成するための
制 御 を取り戻すまで、2 番目のタスクを作成することはできませ
ん。また、それ以降のタスクを作成する場合も同じことが言 え ま
す。したがって、 main() は、そのすべてのタスクを起動した後、
タスクが稼働している間は main() 自身が終了したり、プログラム
全 体 を終了させたりすることがないように、 resultis() または
cancel() を呼び出す必要があります。
どのタスクコンストラクタも、それ自身が新しいタスクを作成でき
ます。
クラス object
クラス object には、1 つのコンストラクタしかありません。この
コンストラクタは引数を持ちません。
object o;
オブジェクト o を作成します (コンストラクタが限定公開で
あ るため、これは正しくありません) 。このオブジェクトは
どのリストにも存在しません。
object *p = o.o_next;
オブジェクトは、一度に 1 つのリスト ( 実 行 チェー ン、
キュー、 その他) にしか存在できません。リストの次のオブ
ジェクトは、公開データメンバー o_next によって指され ま
す。 次のオブジェクトが存在しない場合、また、特に現オブ
ジェクトがどのリストにも属さない場合、このメンバーは ゼ
ロになります。
objtype t = p->o_type();
この仮想関数は、 p が指すオブジェクトの型に対応す る 型
objtype の列挙定数を返します。
int i = p->pending();
p が指すオブジェクトが動作可能でなければ、ゼロ以外の 値
( 真 ) を返します。派生クラスでオブジェクトを待機する場
合、この仮想関数の適切な (独自の) バージョンを定義し な
け ればなりません。クラス object のデフォルトの関数は常
に真 (動作可能でない) を返します。他の定義済みクラス の
そ れぞれには、この関数の独自のバージョンが定義されてい
ます。
o.print(how);
p が指すオブジェクトに関する基本情報を stdout ( cout で
は な い ) に出力します。最初の int 型のパラメタ how で
VERBOSE ビットがセットされていれば、該当するオブジェ ク
ト の「リメンバ・チェーン」に含まれているすべてのタスク
に関する情報を出力します。2 番目の引数は内部で使用す る
た めのもので、デフォルトでゼロに設定されます。通常、こ
の仮想関数は、関数 print() によって派生クラスから呼び出
されます。
o.alert()
タスク o の「リメンバ・チェーン」を検索し、各タス ク の
モードを IDLE から RUNNING に変更して「実行チェーン」に
置きます。あるタスクが保留中のオブジェクトを待機して い
る と、そのタスクは IDLE モードにされ、「実行チェーン」
から除外され、そのオブジェクトの「リメンバ・チェー ン」
に 置かれます。オブジェクトが保留状態でなくなると、定義
済みクラスによってこの関数が自動的に呼びだされ、待機 中
のすべてのオブジェクトが稼働状態になります。
o.forget(p)
タスク o の「リメンバ・チェーン」から、 p が指すタス ク
のすべてのインスタンスを削除します。
o.remember(p)
p が指すタスクを、タスク o の「リメンバ・チェーン」に追
加します。
int user_err_func(int, object*);
object::error_fct = user_err_func;
この関数を用いて、ユーザーはエラー回復を制御できま す。
ユー ザーエラー関数を定義する場合、その関数はパラメタと
して、「診断」の項で示すエラー番号の 1 つ ( int 型 )
と、 オブジェクトへのポインタを持たなければなりません。
このポインタは、関数 object::task_error() を呼び出し た
オ ブ ジェ クト、または下記のようにエラーを処理するオブ
ジェ ク ト に な り ま す。 静 的 デー タ メ ン バー
object::error_fct は、そのようなユーザーエラー関数を指
すように設定できます。このメンバーが設定されていれ ば、
task_error() はユーザー関数を呼び出します。ユーザー関数
がゼロを返すと、 task_error() は制御を戻し、エラーの 原
因 となった操作がおそらく再試行されます。ユーザー関数が
ゼロ以外の値を返した場合、 task_error() は exit() を 呼
び出します。
int i = o.task_error(err, p);
int i = object::task_error(err, p);
この静的メンバー関数は、ランタイム・エラーの発生時に タ
スクシステム関数によって呼び出されます。最初の int 型の
パラメタは、「診断」の項で示すエラーコードのうちの 1 つ
で す。2 番目のパラメタは、通常では、この関数を呼び出し
たオブジェクトです。または、エラーを処理するオブジェ ク
ト がない場合は、ゼロにすることもできます。静的データメ
ンバー error_fct がゼロのとき、 task_error() は stderr
( cerr ではない) にメッセージを出力し、 exit(err) を呼
び出します。 error_fct がゼロ以外のとき、パラメタに err
と p を持つユーザー関数が呼び出されます。このユーザー関
数がゼロを返すと、 task_error() もゼロを返します。 ユー
ザー 関数がゼロ以外の値を返すと、 task_error() は上記の
ように exit(err) を返します。この関数が 0 を返すと、 通
常では、その呼び出し側が失敗した操作を再試行します。
task *tp = o.this_task();
task *tp = object::this_task();
この静的メンバー関数は、現在実行中のタスクへのポイン タ
を返します。
クラス Sched
クラス sched は、基本スケジューリング関数を提供します。 task
と timer は、それぞれこのクラスから派生したものです。このク
ラスのオブジェクトを作成することはできません。基底クラスとし
てのみ機能します。
sched s;
sched 型のオブジェクト s を作成します (このコンストラク
タが限定公開であるため、これは正しくありません)。コンス
トラクタは引数を持ちません。オブジェクトは IDLE に初 期
化され、遅延はありません。
task* tp = ...;
sched::clock_task = tp;
静的データメンバー sched::clock_task がゼロ以外のとき、
そ れが指すタスクはクロックが進むたびに他のどのタスクよ
りも前にスケジューリングされます。現タスクがあ れ ば ブ
ロッ クされ、この「クロックタスク」が再開されます。動作
を再開するとき、クロックタスクは IDLE でなければなり ま
せ ん。 クロックタスクは、 task::sleep() を呼び出すこと
で、自身を IDLE 状態に置くことができます。
void user_exit_func(void);
sched::exit_fct = user_exit_func;
パラメタを何も持たずに void を返す関数を宣言し、それ を
静的データメンバー sched::exit_fct に割り当てることがで
きます。この関数は、タスクシステムから最終的に抜ける 直
前に呼び出されます。
int i = s.pending();
クラス sched では、この関数はオブジェクト ( task または
timer ) が TERMINATED 状態のときはゼロ以外の値 (真)、そ
れ以外の場合はゼロ (偽) を返します。
s.print(how);
オブジェクトの sched 部分に関するデータを stdout ( cout
で はない) に出力します。最初の int 型パラメタ how は、
object::print() に渡されます。2 番目のパラメタは内部 的
に 使用するもので、デフォルトではゼロに初期化されます。
通常、この仮想関数は派生クラスから print() 関数によって
呼び出します。
tp->setwho(objp)
この関数は、クラス task と timer のために用意されていま
す。 これらのクラスについては、後述します。このバージョ
ンを呼び出すとエラーになります。
s.cancel(val);
タスクまたはタイマー s を TERMINATED 状態に置き、その戻
り 値として int 型の値 val を使用します。 resultis() と
は異なり、 cancel() は呼び出し側の動作を中断しませ ん。
こ の関数を使用すると、あるタスクからその制御を保持した
まま別のタスクを終了させることができます。
int i = s.dont_wait();
keep_waiting() が呼び出された回数と、 dont_wait() が 呼
び 出された回数 (この呼び出しはカウントしません) の差を
返します。差を計算した後、カウントはデクリメントされ ま
す。 このカウントは静的変数に保持されるため、システム単
位の差を表すことになります。このカウント値は、外部イ ベ
ン トを待機しているオブジェクトの数を表していると考えら
れます。後述の keep_waiting() を参照してください。
sched *tp = s.get_priority_sched();
特殊なシステムタスクである「割り込み通知タスク」は、 待
機 していたシグナルが発生すると優先的にスケジューリング
されます。この関数は、そのようなタスクがスケジューリ ン
グ されている場合はそのタスクへのポインタを返し、それ以
外の場合はゼロを返します。 interrupt(3C++) も参照してく
ださい。
int i = s.keep_waiting();
keep_waiting() が呼び出された回数と、 dont_wait() が 呼
び出された回数の差を返します。 dont_wait() のこの呼び出
しも回数に含むため、このカウンタは最初にインクリメン ト
さ れます。このカウントは静的変数に保存されるため、シス
テムごとに異なります。このカウントは外部イベントを待 機
し ているオブジェクトの数を表すと考えられます。特に、ク
ラ ス Interrupt_handler の コ ン ス ト ラ ク タ は
keep_waiting() を 呼び出し、デストラクタは dont_wait()
を呼び出します。スケジューラはこの情報を使用するた め、
割 り込みハンドラの稼働時にタスクシステムが終了すること
はありません。
statetype t = s.rdstate();
タスクまたはタイマー s の 状 態 (RUNNING、 IDLE、 TER-
MINATED のどれか) を返します。
long l = s.rdtime();
タスクまたはタイマーを実行するようにスケジューリング さ
れているシミュレートされた時刻を返します。
int i = s.result();
タスク s の 「結 果」 を 返 し ま す。 こ の 結 果 は、
sched::cancel()、 task::cancel()、task::resultis() のど
れかによって設定されます。タスク s が終了してない場合、
そ れ が 終 了 するまで呼び出し側タスクは中断されます。
result() を呼び出してそのタスク自身の結果を返そうとする
と、エラーになります。
long l = s.getclock();
long l = sched::getclock();
現在のシミュレートされた時刻の値を返します。
sched* p = s.get_run_chain();
sched* p = sched::get_run_chain();
実行可能なタスクとタイマーのすべてのリストである「実 行
チェー ン」へのポインタを返します。これらのオブジェクト
は、 o_next フィールドを介してリンクされます。
int i = s.get_exit_status();
int i = sched::get_exit_status();
タスクシステムが正常に ( task_error() の呼び出しが原 因
ではなく) 終了すると、 set_exit_status() に最後に与えら
れた値がシステムルーチン exit() に渡されます。 こ の 値
は、 デ フォ ル ト で は 正 常 終了を示すゼロです。関数
get_exit_status() は、 exit() に渡すために現在登録さ れ
ている値を返します。
s.set_exit_status(i);
sched::set_exit_status(i);
int 型の値 i が保存され、タスクシステ ム が 正 常 に (
task_error() の呼び出しが原因ではなく) 終了すれば、その
値 が シ ス テ ム 関 数 exit() に 渡 さ れ ま す。
set_exit_status() が一度も呼び出されない場合、その値は
正常終 了 を 示 す ゼ ロ で す。 そ れ 以 外 の 場 合、
set_exit_status() に最後に渡された値が使用されます。
s.setclock(l);
sched::setclock(l);
シミュレートされたクロックを long 型の値 l に設定 し ま
す。 システム時間はデフォルトではゼロから始まります。こ
の関数を 2 回以上呼び出すとエラーになります。
クラス task
task t(name, mode, size);
タスクを作成します。パラメタについては、上記を参照し て
く ださい。上記のように、このコンストラクタは限定公開で
あるため、 task はユーザークラスの基底クラスとしてし か
機能できません。
task *tp = t.t_next;
すべてのタスクのマスターリスト上の次のタスク。 後 述 の
get_task_chain() を参照。
unsigned char* p = t.t_name;
コンストラクタ task によって割り当てられたタスク名へ の
ポインタ。
objtype o = t.o_type();
object で定義されているこの仮想関数は、オブジェクトの種
類 を 返します。 task の場合、オブジェクトの種類は TASK
になります。
t.print(how);
task t に関するデータを stdout ( cout ではない) に出 力
し ます。最初の int 型パラメタの how は、VERBOSE ビット
と CHAIN ビットの任意の組み合わせです。VERBOSE がセット
さ れている場合、付加情報が出力されます。CHAIN がセット
されている場合、システム内のタスク 1 つ 1 つに関する 情
報 が出力されます。このパラメタは、 sched::print() に渡
されます。2 番目のパラメタは内部的に使用されるもの で、
デフォルトではゼロに設定されます。
t.setwho(objptr);
仮想関数。 objptr が指すオブジェクトをタスク t に通知を
行 なったオブジェクトとして「再認識」します。これは、タ
スク t がオブジェクト *objptr を待機していたとき、そ の
オ ブ ジェ クトの状態が「保留」から「動作可能」状態に移
り、オブジェクトがそのことをタスクに通知し、タスク状 態
を IDLE から RUNNING に変更したことを意味します。再認識
されたオブジェクトは、 who_alerted_me() によって取り 出
すことができます。
t.cancel(val);
タスク t を TERMINATED 状態に置き、 int 型の値 val をそ
の 戻り値として使用します。 resultis() とは異なり、can-
cel() は呼び出し側の動作を中断しません。これによ り、 1
つ のタスクからその制御を保持したまま別のタスクを終了さ
せることができます。 resultis() も参照してください。
t.delay(n);
シミュレートされた単位時間 n が経過する間、タスク t を
中断し、その状態を RUNNING のままにします。残っている遅
延時間が最も短い RUNNING 状態のタスクが制御を取得し、シ
ミュ レートされたクロックはその継続時間まで進みます。ク
ロックが n 単位進むと、タスク t は実行を再開 し ま す。
delay() を使用しないと、クロックを進めることはできませ
ん。
int i = t.preempt();
RUNNING 状態のタスク t を中断し、それを IDLE 状態にしま
す。この関数は、 t が実行を続けるようにスケジューリング
されている時刻までに残っている単位時間の数を返しま す。
IDLE ま たは TERMINATED 状態のタスクに対して preempt()
を呼び出すとエラーになります。
t.resultis(val);
タスク t を TERMINATED 状態に置き、 int 型の値 val をそ
の 戻り値として使用します。この値は、 t.result() を呼び
出すことで検査できます。タスク t に対して result() を呼
び 出し、そのタスクが終了するのを待機しているすべてのタ
スクに対し、通知が行われます。タスクは、関数が通常使 用
す る方法で値を返すことができないため、終了するときには
resultis() または cancel() を呼び出す必要があります。す
べ てのタスクは、それが終了するまで「保留」状態になりま
す。
t.sleep(objptr);
タスク t を無条件に中断し IDLE 状態にします。省略可能な
引数 objptr は、タスク t を「再認識」し、オブジェクトが
動作可能になったときにそれに通知するオブジェクトへの ポ
インタです。 wait() とは異なり、 sleep() はオブジェクト
が保留中かどうかを最初にチェックしません。タスクは常 に
中断されます。
t.wait(objptr);
objptr が指すオブジェクトが保留中であれば、タスク t を
中断 (IDLE 状態に) します。この場合、そのオブジェクトは
動作可能になると、そのことを t に通知します (タス ク を
RUNNNING 状態に置き、「実行チェーン」に戻します)。オブ
ジェクトが保留中でない場合、タスク t は中断されず、制御
を保持したままとなります。
int which = t.waitlist(op1, op2, ... , NULL);
この関数は、NULL ポインタで終わるオブジェクトへのポイン
タ のリストを引数として受け取ります。指定されたすべての
オブジェクトが保留中の場合、タスク t はそれらのどれかが
動 作可能になるまで中断されます。この関数は、タスクの少
なくとも 1 つが動作可能になると終了し、終了の原因となっ
た オブジェクトのリストのインデックス (0 から始まる) を
返します。この時点で、リストの中の他のオブジェクトも 動
作 可能な場合があります。 waitlist() の呼び出しまでに保
留されているオブジェクトがないと、タスク t は中断 さ れ
ず、 waitlist() は直ちに終了します。
int which = t.waitvec(objarray);
この関数は、 waitlist() とちょうど同じ働きをします。 た
だ し、 waitlist() が引数として可変長のリストを受け取る
のに対し、この関数はオブジェクトへのポインタの配列を 受
け取ります。配列は、NULL ポインタで終わります。
task *tp = t.get_task_chain();
task *tp = task::get_task_chain();
この静的メンバー関数は、すべてのタスクのリストの先頭 を
返します。システム内のすべてのタスクは (RUNNING、IDLE、
TERMINATED どの状態であっても)、データメン バー t_next
を介してリンクされ、このリストに含まれています。
クラス timer
timer tm(d);
シミュレートされた単位時間 d で終了するタイマーを作成し
ます。このタイマーは「実行チェーン」に置かれます。
objtype o = tm.o_type();
object で定義されているこの仮想関数は、オブジェクトの種
類 を 返 し ま す。 timer, の場合、オブジェクトの種類は
TIMER になります。
tm.print(how);
タイマー tm に関する情報を stdout ( cout ではない) に出
力 し ま す。 先 頭 の int 型 パ ラ メタである how は
sched::print() に渡されます。第 2 引数は内部で使用さ れ
るもので、デフォルトではゼロに設定されます。
tm.setwho(objptr);
この仮想関数はタイマーには効果がありません。タイマー に
は通知できないからです。
tm.reset(d);
タイマー tm の遅延をシミュレートされた単位時間 d に再設
定 します。終了しているタイマーでも再設定することができ
ます。すなわち、タイマーは再使用できるため、使用する た
びに作成したり、破棄する必要はありません。
診断
前述のように、タスクシステムはランタイム・エラーを検出 す る
と、 object::task_error() を呼び出します。次の表は、考えられ
る各エラーの値と対応するメッセージとその意味を示しています。
エラー名 メッセージ 説明
___________________________________________________
E_ERROR (メッセージなし) 未定義のエラー
E_OLINK object::delete(): 1 つまたは複数の
has chain オブジェクトが登
録されているリメ
ンバ・チェーンを
持つオブジェクト
を破棄しようとし
た。
___________________________________________________
E_ONEXT object::delete(): on リストに含まれて
chain いるオブジェクト
を破棄しようとし
た。
___________________________________________________
E_GETEMPTY qhead::get(): empty 空のキューからの
取得を試みた。
___________________________________________________
E_PUTOBJ qtail::put(): object すでにキューにあ
on other queue るオブジェクトを
キューに置こうと
した。
___________________________________________________
E_PUTFULL qtail::put(): full フル状態のキュー
にオブジェクトを
置こうとした。
___________________________________________________
E_BACKOBJ qhead::putback(): すでにキューにあ
object on other るオブジェクトを
queue キューに戻そうと
した。
___________________________________________________
E_BACKFULL qhead::putback(): フル状態のキュー
full にオブジェクトを
戻そうとした。
___________________________________________________
E_SETCLOCK sched::setclock(): クロックを 2 度
clock!=0 設 定 しようとし
た。
___________________________________________________
E_CLOCKIDLE sched::schedule(): クロックタスクの
clock_task not idle 実行をスケジュー
リングしようとし
た と き、そのク
ロックタス ク は
IDLE 状態ではな
かった。
___________________________________________________
E_RESTERM sched::insert(): TERMINATED 状 態
cannot schedule ter- のタスクを再開し
minated sched ようとした。
___________________________________________________
E_RESRUN sched::schedule(): RUNNING 状態のタ
running スクを再開しよう
とした。
___________________________________________________
E_NEGTIME sched::schedule(): クロックを負の値
clock<0 に設定しようとし
たか、負の遅延を
使 用 しようとし
た。
___________________________________________________
E_RESOBJ sched::schedule(): すでにキューに置
task or timer on かれているタスク
other queue を再開しようとし
た。
___________________________________________________________
E_HISTO histogram::histogram(): ヒストグラムのコ
bad arguments ンストラクタに対
し、矛盾し た 引
数、または不正な
引数が渡された。
___________________________________________________________
E_STACK task::task() or ランタイムタスク
task::resume(): のスタックがオー
stack overflow バーフローした。
___________________________________________________________
E_STORE new: free store タスク記録のため
exhausted の 空 き領域がな
い。
___________________________________________________________
E_TASKMODE task::task(): bad タスク・コンスト
mode ラクタに対し、不
正なモード引数が
渡された。
___________________________________________________________
E_TASKDEL task::~task(): not TERMINATED 状 態
terminated ではないタスクを
破棄しよう と し
た。
___________________________________________________________
E_TASKPRE task::preempt(): not RUNNING 状態でな
running い タ スクに対し
preempt を実行し
ようとした。
___________________________________________________________
E_TIMERDEL timer::~timer(): not TERMINATED 状 態
terminated でないタスクを破
棄しようとした。
___________________________________________________________
E_SCHTIME sched::schedule(): 実行チェーンが破
runchain corrupted: 棄され、時間順に
bad time なっていない。
___________________________________________________________
E_SCHOBJ sched object used 派生したタスクま
directly (not as たはタイマーでは
base) なく、sched オブ
ジェクトを使用し
ようとした。
___________________________________________________________
E_QDEL queue::~queue(): not 空でないキューを
empty 破 棄 しようとし
た。
___________________________________________________________
E_RESULT task::result(): タスクが自分自身
thistask->result() に 対 し て
result() を呼 び
出そうとした。
___________________________________________________________
E_WAIT task::wait(): wait タスクが自分自身
for self を待機しようとし
た。
___________________________________________________________
E_FUNCS FrameLayout::FrameLayout(): (未使用)
function start
___________________________________________________________
E_FRAMES FrameLayout::FrameLayout(): (未使用)
frame size
___________________________________________________________
E_REGMASK task::fudge_return(): (未使用)
unexpected register
mask
___________________________________________________________
E_FUDGE_SIZE task::fudge_return(): (未使用)
frame too big
___________________________________________________________
E_NO_HNDLR signal_handler - no シグナルが発生し
handler for signal たが、ハンドラが
登録されて い な
い。
___________________________________________________________
E_BADSIG シグナル番号が不正。 不正なシグナル番
号を登録しようと
した。
___________________________________________________________
E_LOSTHNDLR Interrupt_handler:: 内部エラー: シグ
~Interrupt_handler(): ナル・ハンドラが
signal handler not 失われた。
on chain
___________________________________________________________
E_RUNCHAIN sched::sched(): run すべてのタスクが
chain empty 終了し、割り込み
ハンドラが何も存
在しない。
注意事項
この製品出荷の時点では、コルーチンライブラリが現在のバージョ
ン上ではサポートされません。
関連項目
task.intro(3C++)、 interrupt(3C++)、 queue(3C++)、
tasksim(3C++)、 exit(3C)