QUEUE(3C++)

名前
queue - タスクライブラリのリストの管理

形式

#include <task.h>

enum qmodetype { EMODE, WMODE, ZMODE };

class qhead: public object {
public:
	// 公開されたコンストラクタ
	qhead(qmodetype mode=WMODE, int size=10000);

	// 公開された仮想関数
	virtual objtype	o_type();
	virtual int	pending();
	virtual void	print(int, int=0);

	// 公開されたその他の関数
	qhead*	cut();
	object*	get();
	int	putback(object*);
	int	rdcount();
	int	rdmax();
	qmodetype	rdmode();
	void	setmode(qmodetype);
	void 	setmax(int);
	void	splice(qtail*);
	qtail*	tail();
};

class qtail: public object {
public:
	// 公開されたコンストラクタ
	qtail(qmodetype mode=WMODE, int size=10000);

	// 公開された仮想関数
	virtual objtype	o_type();
	virtual int	pending();
	virtual void	print(int, int = 0);

	// 公開されたその他の関数
	qtail*	cut();
	qhead*	head();
	int	put(object*);
	int	rdmax();
	qmodetype	rdmode();
	int	rdspace();
	void	setmode(qmodetype);
	void	setmax(int);
	void	splice(qhead*);
};

機能説明

タスクシステムには、一般的なキューメカニズムが用意されています。 このキューは、クラス object から派生したオブジェクトの先入れ先出しリストです。クラス object に関しては、 task(3C++) を参照してください。 このキュー自体に直接アクセスすることはできませんが、 2 つのクラス qhead および qtail のメンバー関数を用いてアクセスすることができます。クラス qhead により、キューの先頭にアクセスできます。 これは主に、リストの先頭の項目を削除するときに使用します。 qtail クラスにより、キューの終端にアクセスできます。 これは主に、リストの終端に項目を追加するときに使用します。

キューを作成するためには、まず qhead オブジェクトを作成し、 メンバー関数 qhead::tail() を呼び出して対応する qtail にアクセスします。例を示します。
	qhead qh;		// キューを作成
	qtail *qtp = qh.tail();	// qtail を取り出す
また、クラス qtail のオブジェクトを作成した後で、メンバー関数 qtail::head() を用いて対応する qhead にアクセスする方法もあります。 次に示すのは、ヒープ・オブジェクトだけを使用した例です。
	qtail *qtp = new qtail;	// キューを作成
	qhead *qhp = qtp->head();	// qhead を取り出す

この 2 つのクラスのコンストラクタは、 引数にキューのモードとキューの最大サイズの 2 つ (ともに省略可能) を持ちます。 キューモードは、キューの通常の操作には影響を与えず、 保留状態のキューに対する操作を試みた場合に何が発生するかを指定します。 キューモードについては後述します。 キューのサイズは、 キューを構成する項目の最大数です。 これは、最大のサイズを持つ現実のキューをモデル化するのに利用できます。 デフォルトのサイズは 10,000 項目です。 サイズは、メンバー関数 setmax() によっていつでも再設定できます。 キューの各項目に領域があらかじめ割り当てられることはありません。

キューが作成できれば、 メンバー関数 qtail::put() によってそこにオブジェクトを追加したり、 メンバー関数 qhead::get() によってキューの先頭のオブジェクトを取り出すことができます。

クラス object から派生されるすべてのクラスと同様に、 各キューはそれが使用可能であるか保留中であるかの定義を持ち、 その定義はキューの先頭と終端とで異なります。 qtail は、それがフル状態になっている場合、すなわち、 最大数のオブジェクトがすでに含まれている場合は保留状態になります。 qhead は、それが空の場合に保留状態になります。

qhead と qtail はそれぞれのモードを持っていて、 コンストラクタのモード引数によって設定されます。 モードは、メンバー関数 setmode() によっていつでも変更できます。 同じキューの先頭と終端でモードが同じである必要はありません。 モードは、次のいずれかでなければなりません。

WMODE
    待機モード: フル状態の qtail に追加したり、空の qhead から削除を行うように要求があると、その要求を中断します。 他のモードが指定されない場合は、このモードに設定されます。

ZMODE
    ゼロモード : フル状態の qtail に追加したり、空の qhead から削除を行うように要求があると、 ゼロを返します。

EMODE
    エラーモード : フル状態の qtail に追加したり、空の qhead から削除を行うように要求があると、 task_error() を呼び出します。

キューは、カットしたり分割することができます。それにより、 フィルタや他のタスクをキューの処理に挿入することが可能です。 詳細については、メンバー関数 cut() および splice() のところで説明します。

  クラス qhead

qhead qh(m, s);
    qhead 型のオブジェクトとそれに対応するキューを作成します。 キューのモードは m 、最大サイズは s に設定されます。 モードとサイズのパラメタの結果は、上に示したとおりです。 メンバー関数 tail() は、キューに対応する qtail オブジェクトを指すポインタを返します。

objtype ot = qh.o_type();
    この仮想関数は、オブジェクトの種類を返します。 qhead の場合、 オブジェクトの種類は QHEAD となります。

int ispending = qh.pending();
    この仮想関数は、 対応するキューが空の場合はゼロ以外の値 (真) を、 それ以外の場合はゼロ (偽) を返します。

qh.print(how);
    対応するキューに関するデータを stdout ( cout ではない) に出力します。 int 型の第 1 引数 how で VERBOSE ビットがセットされていれば、 キュー内のすべてのオブジェクトに関する情報を出力します。 第 2 引数は内部的に使用するもので、デフォルトはゼロです。

qhead *qhp = qh.cut();
    新しい qhead を作成して元のキューにつなぎ、 そのキューを指すポインタを返します。オリジナルの qhead ( qh ) を新しい空のキューを指すように変更します。 この新しいキューに対応する qtail を取り出す場合は、 qh.tail() を使用してください。 結果として、 qhp はオリジナルの qhead を指すようになり、 オリジナルの qtail はオリジナルのキューに対応したままです。 つまり、次のような状況になります。
    qhp->get()
    オリジナルのキューの先頭の項目を取り出す。
    qhp->tail()->put(op)
    オリジナルのキューにオブジェクトを追加する。
    qh.get()
    新しいキューに項目が登録 (追加) されていれば、その先頭の項目を返す。
    qh.tail()->put(op)
    新しいキューにオブジェクトを追加する。

    この方法により、そのキューのオリジナルの qhead や qtail を使用して、コードを変更することなく 既存のキューにフィルタを挿入することができます。 このフィルタは、 qtail を用いてキューに追加されたオブジェクトを取り出すときには qhp->get() を使用します。 また、新しいキューにオブジェクトを登録 (追加) する場合は、 qhp->tail()->put(op) の等価を使用します。 このようにして追加されたオブジェクトは、オリジナルの qhead を参照するコードによって取り出されます。 オリジナルのキューに対して追加や取り出しを行う既存のコードは、 フィルタを通してオブジェクトを操作するようになります。 キューは、 qhead::splice() によって復元することができます。 qtail には cut と splice の 2 つの関数が対応づけられていますが、 この 2 つの関数のペアは同じオブジェクト ( qhead または qtail のどちらか) から使用しなければなりません。

object *op = qh.get();
    qh に対応するキューが空でなければ、 キューの先頭のオブジェクトを削除し、 それを指すポインタを返します。 キューが空の場合、その動作は、 qh のモードに依存します。モードが WMODE の場合、 get() 呼び出しのタスクはオブジェクトがキューに置かれるまで中断されます。 モードが ZMODE のとき、NULL ポインタを直ちに返します。 モードが EMODE のとき、ランタイム・エラーが発生し、 object::task_error() が呼び出されます。

int ok = qh.putback(op);
    qt に対応するキューがフル状態でなければ、 op が指すオブジェクトをキューの先頭に置き、 値 1 (真) を返します。 qhead と、関数 putback() および get() を使用することで、キューをスタックのように使用できます。 キューがフル状態のとき、動作は qh のモードに依存します。 モードが WMODE の場合、 putback() を呼び出すタスクは、 キューがフルではない状態になるまで中断されます。 モードが ZMODE の場合、直ちにゼロを返します。 モードが EMODE の場合、ランタイム・エラーが発生し、 object::task_error() が呼び出されます。

int i = qh.rdcount();
    対応するキューに現在含まれているオブジェクトの数を返します。

int i = qh.rdmax();
    対応するキューに入れることができるオブジェクトの (現在の) 最大数を返します。

qmodetype qm = qh.rdmode();
    qh の現在のモード (WMODE、EMODE、ZMODE のいずれか) を返します。

qh.setmode(qm);
    qh のモードを qm に設定します。 qm は、WMODE、EMODE、ZMODE のいずれかです。

qh.setmax(max);
    対応するキューに入れることができる項目の最大数を max に設定します。 最大数は、 キュー内の現在のオブジェクトの数より小さい値に設定することができます。 この場合、オブジェクトを削除してキュー内のオブジェクト数を 最大数より少なくしないかぎり、キューはフル状態であると見なされます。

qhp->splice(qtp);
    qhead::cut() による前回の操作の逆の操作を行います。ここで、 qhp は cut() によって返されたポインタ、 qtp は qhp に対応する qtail オブジェクトを指すポインタです。 ここで、これらの先頭および終端を指すポインタは、 それぞれ別のキューに属しています。 splice() により、2 つのキューがマージされ、 qhp および qtp がそれぞれ指している qhead オブジェクトと qtail オブジェクトを削除します。 マージされたキューの中では、 qtp が指すキューのすべてのオブジェクトは、 qhp が指すキューのどのオブジェクトよりも前に配置されます。 この復元後のキューは再度、オリジナルの cut() が行われたオリジナルの qhead オブジェクトおよび qtail オブジェクトに対応づけられます。 マージにより、それまでフル状態であったキューがフル状態でなくなる場合、 または空のキューが空でなくなる場合、 その状態を待機しているすべてのタスクに通知します (タスクは 実行可能になります)。 task(3C++) を参照。

qtail *qtp = qh.tail();
    キューに対応する qtail オブジェクトを指すポインタを返します。 qtail が存在しない場合は新しく作成します。

  クラス qtail

qtail qt(m, s);
    qtail オブジェクトと、それに対応するキューを作成します。 新しいキューのモードは m 、最大のサイズは s に設定されます。 モードおよびサイズのパラメタの結果については、 上記を参照してください。メンバー関数 head() は、キューに対応する qhead オブジェクトを指すポインタを返します。

objtype ot = qt.o_type();
    この仮想関数は、 オブジェクトの種類を返します。 qtail の場合、オブジェクトの種類は QTAIL です。

int ispending = qt.pending();
    この仮想関数は、対応するキューがフル状態であればゼロ以外の値 (真) を、 そうでなければゼロ (偽) を返します。

qt.print(how);
    対応するキューについてのデータを stdout ( cout ではない) に出力します。 int 型の第 1 引数 how の VERBOSE ビットがセットされていれば、 キュー内のすべてのオブジェクトに関する情報を出力します。 第 2 引数は内部的に使用するもので、デフォルトはゼロです。

qtail *qtp = qt.cut();
    新しい qtail オブジェクトを作成してオリジナルのキューに追加し、 そのオブジェクトを指すポインタを返します。 オリジナルの qtail ( qt ) を新しい空のキューを指すように変更します。 この新しいキューに対応する qhead を取り出す場合は、 qt.head() を使用してください。 結果として、 qtp はオリジナルの qtail を指すようになり、 qhead はオリジナルのキューに対応したままです。 つまり、次のような状況になります。
    qtp->head()->get()
    オリジナル・キューの先頭の項目を取り出す。 すなわち、オリジナルの qhead はまだ、オリジナルのキューから項目を取り出す。
    qtp->put(op)
    オリジナルのキューにオブジェクトを追加する。
    qt.head()->get()
    新しいキューに項目が登録 (追加) されていれば、 その先頭の項目を返す。
    qt.put(op)
    新しいキューにオブジェクトを追加する。

    この方法により、そのキューのオリジナルの qhead や qtail を使用し、コードを変更することなく 既存のキューにフィルタを挿入することができます。 フィルタは、オリジナルの qtail を用いてキューに登録 (追加) されたオブジェクトを取り出すときには qtp->head()->get() の等価を使用します。 また、オリジナルのキューにオブジェクトを追加する場合は qtp->put(op) を使用します。このようにして追加されたオブジェクトは、 qhead を参照しているコードによって取り出されます。 オリジナルのキューに対して追加や取り出しを行う既存のコードは、 フィルタを通してオブジェクトを操作するようになります。 キューは qtail::splice() によって復元できます。 qhead には cut と splice の 2 つの関数が対応づけられていますが、 この 2 つの関数のペアは同じオブジェクト ( qhead または qtail のどちらか) から使用しなければなりません。

qhead *qtp = qt.head();
    キューに対応する qhead を指すポインタを返します。 qhead が存在しない場合は新しく作成します。

int ok = qt.put(op);
    qt に対応するキューがフル状態でなければ op が指すオブジェクトをそのキューに追加し、 値 1 (真) を返します。 キューがフル状態であるとき、動作は qt のモードに依存します。モードが WMODE の場合、 put() を呼び出すタスクはキューがフル状態でなくなるまで中断されます。 モードが ZMODE の場合は直ちにゼロを返します。 モードが EMODE の場合はランタイム・エラーが発生し、 object::task_error() が呼び出されます。

int i = qt.rdmax();
    対応するキューに入れることができるオブジェクトの (現在の) 最大数を返します。

qmodetype qm = qt.rdmode();
    qt の現在のモード (WMODE、EMODE、ZMODE のいずれか) を返します。

int i = qt.rdspace();
    フル状態になる前に、対応するキューに追加できるオブジェクトの数を返します。

qt.setmode(qm);
    qt のモードを qm に設定します。 qm は、WMODE、EMODE、ZMODE のいずれかです。

qt.setmax(max);
    対応するキューに入れることができる項目の最大数を max に設定します。 最大数は、 キュー内の現在のオブジェクトの数より小さい値に設定することができます。 この場合、オブジェクトを削除してキュー内のオブジェクト数を 最大数より少なくしないかぎり、キューはフル状態であると見なされます。

qtp->splice(qhp);
    qtail::cut() による前回の操作の逆の操作を行います。 qtp は cut() によって返されたポインタ、 qhp は qtp に対応する qhead オブジェクトを指すポインタです。 ここで、先頭および終端を指すこれらのポインタは、 それぞれ別のキューに属しています。 splice() により、2 つのキューがマージされ、 qhp と qtp がそれぞれ指している qhead オブジェクトと qtail オブジェクトを削除します。 マージされたキューの中では、 qtp が指すキューのすべてのオブジェクトは、 qhp が指すキューのどのオブジェクトよりも前に配置されます。 この復元後のキューは再度、オリジナルの cut() が行われたオリジナルの qhead オブジェクトと qtail オブジェクトに対応づけられます。 マージにより、それまでフル状態であったキューがフル状態でなくなる場合、 または空のキューが空でなくなる場合、 その状態を待機しているすべてのタスクに通知されます (タスクは 実行可能になります)。 task(3C++) を参照。

診断

task(3C++) を参照してください。

関連項目
task.intro(3C++), interrupt(3C++), task(3C++), tasksim(3C++)