マニュアルページ task.intro.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)