QUEUE

Section: Linux Programmer's Manual (3)
Updated: 2007-12-28
IndexJM Home Page
 

名前

LIST_ENTRY, LIST_HEAD, LIST_INIT, LIST_INSERT_AFTER, LIST_INSERT_HEAD, LIST_REMOVE, TAILQ_ENTRY, TAILQ_HEAD, TAILQ_INIT, TAILQ_INSERT_AFTER, TAILQ_INSERT_HEAD, TAILQ_INSERT_TAIL, TAILQ_REMOVE, CIRCLEQ_ENTRY, CIRCLEQ_HEAD, CIRCLEQ_INIT, CIRCLEQ_INSERT_AFTER, CIRCLEQ_INSERT_BEFORE, CIRCLEQ_INSERT_HEAD, CIRCLEQ_INSERT_TAIL, CIRCLEQ_REMOVE - リスト・テール (tail) キュー・循環キューの実装 

書式

#include <sys/queue.h>LIST_ENTRY(TYPE);LIST_HEAD(HEADNAME, TYPE);LIST_INIT(LIST_HEAD *head);LIST_INSERT_AFTER(LIST_ENTRY *listelm,  TYPE *elm, LIST_ENTRY NAME);LIST_INSERT_HEAD(LIST_HEAD *head,  TYPE *elm, LIST_ENTRY NAME);LIST_REMOVE(TYPE *elm, LIST_ENTRY NAME);TAILQ_ENTRY(TYPE);TAILQ_HEAD(HEADNAME, TYPE);TAILQ_INIT(TAILQ_HEAD *head);TAILQ_INSERT_AFTER(TAILQ_HEAD *head, TYPE *listelm,  TYPE *elm, TAILQ_ENTRY NAME);TAILQ_INSERT_HEAD(TAILQ_HEAD *head,  TYPE *elm, TAILQ_ENTRY NAME);TAILQ_INSERT_TAIL(TAILQ_HEAD *head,  TYPE *elm, TAILQ_ENTRY NAME);TAILQ_REMOVE(TAILQ_HEAD *head, TYPE *elm, TAILQ_ENTRY NAME);CIRCLEQ_ENTRY(TYPE);CIRCLEQ_HEAD(HEADNAME, TYPE);CIRCLEQ_INIT(CIRCLEQ_HEAD *head);CIRCLEQ_INSERT_AFTER(CIRCLEQ_HEAD *head, TYPE *listelm,  TYPE *elm, CIRCLEQ_ENTRY NAME);CIRCLEQ_INSERT_BEFORE(CIRCLEQ_HEAD *head, TYPE *listelm,  TYPE *elm, CIRCLEQ_ENTRY NAME);CIRCLEQ_INSERT_HEAD(CIRCLEQ_HEAD *head,  TYPE *elm, CIRCLEQ_ENTRY NAME);CIRCLEQ_INSERT_TAIL(CIRCLEQ_HEAD *head,  TYPE *elm, CIRCLEQ_ENTRY NAME);CIRCLEQ_REMOVE(CIRCLEQ_HEAD *head,  TYPE *elm, CIRCLEQ_ENTRY NAME);
 

説明

これらのマクロは、次の 3 つのデータ構造を定義して操作する: リスト・テールキュー・循環キュー。 3 つのデータ構造すべてにおいて以下の機能がサポートされている:

*
新たなエントリーをリストの先頭に挿入する。
*
新たなエントリーをリストのどの要素よりも後に挿入する。
*
リストの任意のエントリーを削除する。
*
リストを順方向に辿る。

リストは 3 つのデータ構造の中で最も単純であり、 上記の機能のみをサポートする。

テールキューは以下の機能を追加する:

*
エントリーをリストの最後に追加できる。

ただし:

1.
全てのリスト挿入と削除において、リストの先頭を指定しなければならない。
2.
各先頭エントリーは 1 つではなく 2 つのポインターを必要とする。
3.
リストと比べて、コードサイズは 15% 大きくなり、操作は 20% 遅くなる。

循環キューは以下の機能を追加する:

*
エントリーをリストの最後に追加できる。
*
エントリーを他のエントリーの前に追加できる。
*
逆方向に末尾から先頭へ辿ることができる。

ただし:

1.
全てのリスト挿入と削除において、リストの先頭を指定しなければならない。
2.
各先頭エントリーは 1 つではなく 2 つのポインターを必要とする。
3.
辿る際の終了条件がより複雑である。
4.
リストと比べて、コードサイズは 40% 大きくなり、操作は 45% 遅くなる。

マクロ定義において TYPE はユーザー定義構造体の名前であり、 LIST_ENTRY, TAILQ_ENTRY,CIRCLEQ_ENTRY の何れか型のフィールドと 指定された NAME を含まなければならない。 引き数 HEADNAMEはユーザー定義構造体の名前であり、 マクロ LIST_HEAD, TAILQ_HEAD, CIRCLEQ_HEADを用いて宣言されなければならない。 これらのマクロがどのように使われるかについての更なる説明は、 以下の例を参照すること。 

リスト

リストの先頭には、 LIST_HEAD マクロで定義される構造体が置かれる。 この構造体はリストの最初の要素へのポインターを 1 つ含む。 要素は 2 重にリンクされており、 任意の要素はリストを辿らずに削除できる。 新しい要素は既存の要素の後またはリストの先頭に追加できる。LIST_HEAD 構造体は以下のように宣言されている:
LIST_HEAD(HEADNAME, TYPE) head;

ここで HEADNAME は定義される構造体の名前であり、 TYPE はリンク内でリンクされる要素の型である。 リストの先頭へのポインターは、その後で次のように宣言される:

struct HEADNAME *headp;

(名前 headheadp はユーザーが選択できる。)

マクロ LIST_ENTRY はリストの要素を接続する構造体を宣言する。

マクロ LIST_INIThead で参照されるリストを初期化する。

マクロ LIST_INSERT_HEAD は新たな要素 elm をリストの先頭に挿入する。

マクロ LIST_INSERT_AFTER は新たな要素 elm を要素 listelm の後に挿入する。

マクロ LIST_REMOVE は要素 elm をリストから削除する。 

リストの例

LIST_HEAD(listhead, entry) head;
struct listhead *headp;
struct entry { ... LIST_ENTRY(entry) entries; ...
} *n1, *n2, *np;
LIST_INIT(&head);
n1 = malloc(sizeof(struct entry));
LIST_INSERT_HEAD(&head, n1, entries);
n2 = malloc(sizeof(struct entry));
LIST_INSERT_AFTER(n1, n2, entries);
for (np = head.lh_first; np != NULL; np = np->entries.le_next) np-> ...
while (head.lh_first != NULL) LIST_REMOVE(head.lh_first, entries);
 

テールキュー

テールキューの先頭には TAILQ_HEAD マクロで定義される構造体が置かれる。 この構造体は 1 組のポインターを含んでいる。 1 つはテールキューの最初の要素へのポインターであり、 もう 1 つはテールキューの最後の要素へのポインターである。 要素は 2 重にリンクされており、 任意の要素はテールキューを辿らずに削除できる。 新しい要素は既存の要素の後またはテールキューの先頭または末尾に追加できる。 TAILQ_HEAD構造体は以下のように定義されている:
TAILQ_HEAD(HEADNAME, TYPE) head;

ここで HEADNAME は定義される構造体の名前であり、 TYPE はテールキュー内でリンクされる要素の型である。 テールキューの先頭へのポインターは、その後で次のように宣言される:

struct HEADNAME *headp;

(名前 headheadp はユーザーが選択できる。)

マクロ TAILQ_ENTRY はテールキューの要素を接続する構造体を宣言する。

マクロ TAILQ_INIThead で参照されるテールキューを初期化する。

マクロ TAILQ_INSERT_HEAD は新たな要素 elm をテールキューの先頭に挿入する。

マクロ TAILQ_INSERT_TAIL は新たな要素 elm をテールキューの末尾に挿入する。

マクロ TAILQ_INSERT_AFTER は新たな要素 elm を要素 listelm の後に挿入する。

マクロ TAILQ_REMOVE は要素 elm をテールキューから削除する。 

テールキューの例

TAILQ_HEAD(tailhead, entry) head;
struct tailhead *headp;
struct entry { ... TAILQ_ENTRY(entry) entries; ...
} *n1, *n2, *np;
TAILQ_INIT(&head);
n1 = malloc(sizeof(struct entry));
TAILQ_INSERT_HEAD(&head, n1, entries);
n1 = malloc(sizeof(struct entry));
TAILQ_INSERT_TAIL(&head, n1, entries);
n2 = malloc(sizeof(struct entry));
TAILQ_INSERT_AFTER(&head, n1, n2, entries);
for (np = head.tqh_first; np != NULL; np = np->entries.tqe_next) np-> ...
while (head.tqh_first != NULL) TAILQ_REMOVE(&head, head.tqh_first, entries);
 

循環キュー

循環キューの先頭には CIRCLEQ_HEAD マクロで定義される構造体が置かれる。 この構造体は 1 組のポインターを含んでいる。 1 つは循環キューの最初の要素へのポインターであり、 もう 1 つは循環キューの最後の要素へのポインターである。 要素は 2 重にリンクされており、 任意の要素はキューを辿らずに削除できる。 新しい要素は、既存の要素の後または前、またはキューの先頭または末尾に追加できる。 ACIRCLEQ_HEAD 構造体は以下のように定義されている:
CIRCLEQ_HEAD(HEADNAME, TYPE) head;

ここで HEADNAME は定義される構造体の名前であり、 TYPE は循環キュー内でリンクされる要素の型である。 循環キューの先頭へのポインターは、その後で次のように宣言される:

struct HEADNAME *headp;

(名前 headheadp はユーザーが選択できる。)

マクロ CIRCLEQ_ENTRY は循環キューの要素を接続する構造体を宣言する。

マクロ CIRCLEQ_INIThead で参照される循環キューを初期化する。

マクロ CIRCLEQ_INSERT_HEAD は新たな要素 elm を循環キューの先頭に挿入する。

マクロ CIRCLEQ_INSERT_TAIL は新たな要素 elm を循環キューの末尾に挿入する。

マクロ CIRCLEQ_INSERT_AFTER は新たな要素 elm を要素 listelm の後に挿入する。

マクロ CIRCLEQ_INSERT_AFTER は新たな要素 elm を要素 listelm の前に挿入する。

マクロ CIRCLEQ_REMOVE は要素 elm を循環キューから削除する。 

循環キューの例

CIRCLEQ_HEAD(circleq, entry) head;
struct circleq *headp;
struct entry { ... CIRCLEQ_ENTRY(entry) entries; ...
} *n1, *n2, *np;
CIRCLEQ_INIT(&head);
n1 = malloc(sizeof(struct entry));
CIRCLEQ_INSERT_HEAD(&head, n1, entries);
n1 = malloc(sizeof(struct entry));
CIRCLEQ_INSERT_TAIL(&head, n1, entries);
n2 = malloc(sizeof(struct entry));
CIRCLEQ_INSERT_AFTER(&head, n1, n2, entries);
n2 = malloc(sizeof(struct entry));
CIRCLEQ_INSERT_BEFORE(&head, n1, n2, entries);
for (np = head.cqh_first; np != (void *)&head; np = np->entries.cqe_next) np-> ...
for (np = head.cqh_last; np != (void *)&head; np = np->entries.cqe_prev) np-> ...
while (head.cqh_first != (void *)&head) CIRCLEQ_REMOVE(&head, head.cqh_first, entries);
 

準拠

POSIX.1-2001 にはない。 BSD 系に存在する。 queue 関数は 4.4BSD で初めて登場した。 

この文書について

この man ページは Linux man-pages プロジェクトのリリース 3.79 の一部 である。プロジェクトの説明とバグ報告に関する情報はhttp://www.kernel.org/doc/man-pages/ に書かれている。


関連キーワード

CIRCLEQ,キュー,TAILQ,LIST,ENTRY,TYPE,INSERT,リスト,マクロ,elm 

Index

名前
書式
説明
リスト
リストの例
テールキュー
テールキューの例
循環キュー
循環キューの例
準拠
この文書について

This document was created byman2html, using the manual pages.
Time: 20:43:06 GMT, August 08, 2017