glibcにおけるキューの使用方法


今日DPDKソースコードを見ると、glibcで提供されているキューAPIが使用されていることがわかりました.これらのAPIはヘッダファイルに含まれており、使いやすいです.今日はmanマニュアルを見て、これらのAPIの使い方を記録しました.
最初のキューはsingly-linked listsです.一方向チェーンテーブルでは、挿入操作はヘッダへの挿入のみをサポートするため、通常はLIFO(後進先出キュー)を実現するために使用される.
2つ目のキューはsingly-linked tail queuesです.一方向チェーンテーブルは、テールへの挿入操作が追加されたため、FIFO(先進的な先頭キュー)を実現するために一般的に使用される.
3つ目はlistsです.双方向チェーンテーブルで、挿入操作は頭部への挿入のみをサポートします.双方向ループをサポートします.
4つ目はtail queuesです.ヘッドとテールへの挿入をサポートする双方向チェーンテーブル.双方向ループをサポートします.
次にsingly-linked listsを例に、これらのAPIの使用方法について説明します.
まず、例で使用する構造体の名前をentryと定義します.カスタムデータメンバー(val)のほかに、SLIST_を使用する必要があります.ENTRY(TYPE)定義のメンバー.TYPEは構造体名「entry」でなければなりません.メンバー名は「entries」で任意に名前を付けることができます.これにより、このデータ構造はチェーンテーブルAPIを使用して管理することができます.次のようになります.
struct entry {
    /*    */
    int val;
    SLIST_ENTRY(entry) entries;     /* Singly-linked List. */
}

次にSLIST_を使用HEAD(HEADNAME,TYPE)はチェーンテーブルヘッダとしての新しい構造体を定義し,HEADNAMEは新しい構造体名,TYPEは我々がカスタマイズした構造体名である.次に示すように、例で使用する新しい構造体の名前は「slisthead」です.
SLIST_HEAD(slisthead, entry);

次に、チェーンテーブルのヘッダ変数を定義し、初期化します.
struct slisthead head = SLIST_HEAD_INITIALIZER(head);
SLIST_INIT(&head);

次に、APIを使用してチェーンテーブルにデータを挿入できます.具体的には、次の例を参照してください.

singly-linked lists

#include 
#include 
#include 

int main(int argc, char **argv)
{
     SLIST_HEAD(slisthead, entry) head = SLIST_HEAD_INITIALIZER(head);
     struct slisthead *headp;                /* Singly-linked List head. */
     struct entry {
             int val;
             SLIST_ENTRY(entry) entries;     /* Singly-linked List. */
     } *n1, *n2, *n3, *np;

     SLIST_INIT(&head);                      /* Initialize the list. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     SLIST_INSERT_HEAD(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     SLIST_INSERT_AFTER(n1, n2, entries);

     SLIST_FOREACH(np, &head, entries) {     /* Forward traversal. */
        printf("val = %d
"
, np->val); } SLIST_REMOVE(&head, n2, entry, entries);/* Deletion. */ free(n2); n3 = SLIST_FIRST(&head); SLIST_REMOVE_HEAD(&head, entries); /* Deletion from the head. */ free(n3); while (!SLIST_EMPTY(&head)) { /* List Deletion. */ n1 = SLIST_FIRST(&head); SLIST_REMOVE_HEAD(&head, entries); free(n1); } }

singly-linked tail queues

#include 
#include 
#include 

int main(int argc, char **argv)
{
     STAILQ_HEAD(stailhead, entry) head = STAILQ_HEAD_INITIALIZER(head);
     struct stailhead *headp;                /* Singly-linked tail queue head. */
     struct entry {
             int val;
             STAILQ_ENTRY(entry) entries;    /* Tail queue. */
     } *n1, *n2, *n3, *np;

     STAILQ_INIT(&head);                     /* Initialize the queue. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     STAILQ_INSERT_HEAD(&head, n1, entries);

     n1 = malloc(sizeof(struct entry));      /* Insert at the tail. */
     STAILQ_INSERT_TAIL(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     STAILQ_INSERT_AFTER(&head, n1, n2, entries);
                                             /* Deletion. */
     STAILQ_REMOVE(&head, n2, entry, entries);
     free(n2);
                                             /* Deletion from the head. */
     n3 = STAILQ_FIRST(&head);
     STAILQ_REMOVE_HEAD(&head, entries);
     free(n3);
                                             /* Forward traversal. */
     STAILQ_FOREACH(np, &head, entries) {
            printf("val = %d
"
, np->val); } /* TailQ Deletion. */ while (!STAILQ_EMPTY(&head)) { n1 = STAILQ_FIRST(&head); STAILQ_REMOVE_HEAD(&head, entries); free(n1); } /* Faster TailQ Deletion. */ n1 = STAILQ_FIRST(&head); while (n1 != NULL) { n2 = STAILQ_NEXT(n1, entries); free(n1); n1 = n2; } STAILQ_INIT(&head); }

lists

#include 
#include 
#include 

int main(int argc, char **argv)
{
     LIST_HEAD(listhead, entry) head =
         LIST_HEAD_INITIALIZER(head);
     struct listhead *headp;                 /* List head. */
     struct entry {
             int val;
             LIST_ENTRY(entry) entries;      /* List. */
     } *n1, *n2, *n3, *np, *np_temp;

     LIST_INIT(&head);                       /* Initialize the list. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     LIST_INSERT_HEAD(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     LIST_INSERT_AFTER(n1, n2, entries);

     n3 = malloc(sizeof(struct entry));      /* Insert before. */
     LIST_INSERT_BEFORE(n2, n3, entries);

     LIST_REMOVE(n2, entries);               /* Deletion. */
     free(n2);
                                             /* Forward traversal. */
     LIST_FOREACH(np, &head, entries) {
             printf("val = %d
"
, np->val); } while (!LIST_EMPTY(&head)) { /* List Deletion. */ n1 = LIST_FIRST(&head); LIST_REMOVE(n1, entries); free(n1); } n1 = LIST_FIRST(&head); /* Faster List Deletion. */ while (n1 != NULL) { n2 = LIST_NEXT(n1, entries); free(n1); n1 = n2; } LIST_INIT(&head); }

tail queues

#include 
#include 
#include 

int main(int argc, char **argv)
{
     TAILQ_HEAD(tailhead, entry) head = TAILQ_HEAD_INITIALIZER(head);
     struct tailhead *headp;                 /* Tail queue head. */
     struct entry {
             int val;
             TAILQ_ENTRY(entry) entries;     /* Tail queue. */
     } *n1, *n2, *n3, *np;

     TAILQ_INIT(&head);                      /* Initialize the queue. */

     n1 = malloc(sizeof(struct entry));      /* Insert at the head. */
     n1->val = 1;
     TAILQ_INSERT_HEAD(&head, n1, entries);

     n1 = malloc(sizeof(struct entry));      /* Insert at the tail. */
     n1->val = 2;
     TAILQ_INSERT_TAIL(&head, n1, entries);

     n2 = malloc(sizeof(struct entry));      /* Insert after. */
     n2->val = 3;
     TAILQ_INSERT_AFTER(&head, n1, n2, entries);

     n3 = malloc(sizeof(struct entry));      /* Insert before. */
     n3->val = 4;
     TAILQ_INSERT_BEFORE(n2, n3, entries);

     TAILQ_REMOVE(&head, n2, entries);       /* Deletion. */
     free(n2);
                                             /* Forward traversal. */
     TAILQ_FOREACH(np, &head, entries) {
             printf("val = %d
"
, np->val); } /* Reverse traversal. */ TAILQ_FOREACH_REVERSE(np, &head, tailhead, entries) { printf("val = %d
"
, np->val); } /* TailQ Deletion. */ while (!TAILQ_EMPTY(&head)) { n1 = TAILQ_FIRST(&head); TAILQ_REMOVE(&head, n1, entries); free(n1); } /* Faster TailQ Deletion. */ n1 = TAILQ_FIRST(&head); while (n1 != NULL) { n2 = TAILQ_NEXT(n1, entries); free(n1); n1 = n2; } TAILQ_INIT(&head); }