tail queue in queue.h for free bsd.

来源:互联网 发布:megadownloader mac 编辑:程序博客网 时间:2024/06/06 03:21
tail queue in queue.h for free bsd
2009-09-27 14:17

38 /*
67 * A tail queue is headed by a pair of pointers, one to the head of the
   68 * list and the other to the tail of the list. The elements are doubly
   69 * linked so that an arbitrary element can be removed without a need to
   70 * traverse the list. New elements can be added to the list before or
   71 * after an existing element, at the head of the list, or at the end of
   72 * the list. A tail queue may be traversed in either direction.
   83 */
  

303 /*
304 * Tail queue definitions.
305 */
306 #define TAILQ_HEAD(name, type)                                          /
307 struct name {                                                           /
308         struct type *tqh_first; /* first element */                     /
309         struct type **tqh_last; /* addr of last next element */         /
310 }
311
312 #define TAILQ_HEAD_INITIALIZER(head)                                    /
313         { NULL, &(head).tqh_first }
314
315 #define TAILQ_ENTRY(type)                                               /
316 struct {                                                                /
317         struct type *tqe_next; /* next element */                      /
318         struct type **tqe_prev; /* address of previous next element */ /
319 }
320
321 /*
322 * tail queue access methods
323 */
324 #define TAILQ_FIRST(head)               ((head)->tqh_first)
325 #define TAILQ_END(head)                 NULL
326 #define TAILQ_NEXT(elm, field)          ((elm)->field.tqe_next)
327 #define TAILQ_LAST(head, headname)                                      /
328         (*(((struct headname *)((head)->tqh_last))->tqh_last))
329 /* XXX */
330 #define TAILQ_PREV(elm, headname, field)                                /
331         (*(((struct headname *)((elm)->field.tqe_prev))->tqh_last))
332 #define TAILQ_EMPTY(head)                                               /
333         (TAILQ_FIRST(head) == TAILQ_END(head))
334
335 #define TAILQ_FOREACH(var, head, field)                                 /
336         for((var) = TAILQ_FIRST(head);                                  /
337             (var) != TAILQ_END(head);                                   /
338             (var) = TAILQ_NEXT(var, field))
339
340 #define TAILQ_FOREACH_REVERSE(var, head, headname, field)               /
341         for((var) = TAILQ_LAST(head, headname);                         /
342             (var) != TAILQ_END(head);                                   /
343             (var) = TAILQ_PREV(var, headname, field))
344
345 /*
346 * Tail queue functions.
347 */
348 #define TAILQ_INIT(head) do {                                           /
349         (head)->tqh_first = NULL;                                       /
350         (head)->tqh_last = &(head)->tqh_first;                          /
351 } while (0)
352
353 #define TAILQ_INSERT_HEAD(head, elm, field) do {                        /
354         if (((elm)->field.tqe_next = (head)->tqh_first) != NULL)        /
355                 (head)->tqh_first->field.tqe_prev =                     /
356                     &(elm)->field.tqe_next;                             /
357         else                                                            /
358                 (head)->tqh_last = &(elm)->field.tqe_next;              /
359         (head)->tqh_first = (elm);                                      /
360         (elm)->field.tqe_prev = &(head)->tqh_first;                     /
361 } while (0)
362
363 #define TAILQ_INSERT_TAIL(head, elm, field) do {                        /
364         (elm)->field.tqe_next = NULL;                                   /
365         (elm)->field.tqe_prev = (head)->tqh_last;                       /
366         *(head)->tqh_last = (elm);                                      /
367         (head)->tqh_last = &(elm)->field.tqe_next;                      /
368 } while (0)
369
370 #define TAILQ_INSERT_AFTER(head, listelm, elm, field) do {              /
371         if (((elm)->field.tqe_next = (listelm)->field.tqe_next) != NULL)/
372                 (elm)->field.tqe_next->field.tqe_prev =                 /
373                     &(elm)->field.tqe_next;                             /
374         else                                                            /
375                 (head)->tqh_last = &(elm)->field.tqe_next;              /
376         (listelm)->field.tqe_next = (elm);                              /
377         (elm)->field.tqe_prev = &(listelm)->field.tqe_next;             /
378 } while (0)
379
380 #define TAILQ_INSERT_BEFORE(listelm, elm, field) do {                   /
381         (elm)->field.tqe_prev = (listelm)->field.tqe_prev;              /
382         (elm)->field.tqe_next = (listelm);                              /
383         *(listelm)->field.tqe_prev = (elm);                             /
384         (listelm)->field.tqe_prev = &(elm)->field.tqe_next;             /
385 } while (0)
386
387 #define TAILQ_REMOVE(head, elm, field) do {                             /
388         if (((elm)->field.tqe_next) != NULL)                            /
389                 (elm)->field.tqe_next->field.tqe_prev =                 /
390                     (elm)->field.tqe_prev;                              /
391         else                                                            /
392                 (head)->tqh_last = (elm)->field.tqe_prev;               /
393         *(elm)->field.tqe_prev = (elm)->field.tqe_next;                 /
394         _Q_INVALIDATE((elm)->field.tqe_prev);                           /
395         _Q_INVALIDATE((elm)->field.tqe_next);                           /
396 } while (0)
397
398 #define TAILQ_REPLACE(head, elm, elm2, field) do {                      /
399         if (((elm2)->field.tqe_next = (elm)->field.tqe_next) != NULL)   /
400                 (elm2)->field.tqe_next->field.tqe_prev =                /
401                     &(elm2)->field.tqe_next;                            /
402         else                                                            /
403                 (head)->tqh_last = &(elm2)->field.tqe_next;             /
404         (elm2)->field.tqe_prev = (elm)->field.tqe_prev;                 /
405         *(elm2)->field.tqe_prev = (elm2);                               /
406         _Q_INVALIDATE((elm)->field.tqe_prev);                           /
407         _Q_INVALIDATE((elm)->field.tqe_next);                           /
408 } while (0)


Tail queue 使用例子:
test1.c

#include <stdio.h>
#include "queue.h"


#define REPEAT 500
#define NOBJECTS 1000000

// 在程序中如果我们想使用queue.h中提供的东西来
// 简便地将自己的数据存储在队列中,就要定义如下的结构体:
// 结构体中前面几项是自己的数据,最后一项是 TAILQ_ENTRY(..)...
// 当然,如果最后一项根据自己选择的队列类型也可以是
// SLIST_ENTRY或LIST_ENTRY或SIMPLEQ_ENTRY或CIRCLEQ_ENTRY
struct object{
    char anything[7]; // 这里我们自己的数据很简单,是字符数组
    TAILQ_ENTRY(object) tailq_entry;
};

 

struct object objects[NOBJECTS];

TAILQ_HEAD(,object) the_tailq;   // 定义TAILQ队列头(definations)
TAILQ_INIT(&the_tailq);          // 初始化TAILQ队列头(functions)

static void test_tailq(){
    int t;
    puts("Testing TAILQ...");
    for (t = 0; t < REPEAT; t++) {
        int i;

        for (i = 0; i < NOBJECTS; i++) {
            TAILQ_INSERT_TAIL(&the_tailq, objects+i, tailq_entry);
        }
        for (i = 0; i < NOBJECTS; i++) {
            TAILQ_REMOVE_HEAD(&the_tailq, tailq_entry);
        }
    }
}


int main(){

    test_stailq();

    return 0;
}

test2.c


#include <stdio.h>  
#include <stdlib.h>  
#include "queue.h"  
  
struct QUEUE_ITEM{  
    int value;  
    TAILQ_ENTRY(QUEUE_ITEM) entries;  
};  
TAILQ_HEAD(,QUEUE_ITEM) queue_head;  
int main(int argc,char **argv){  
    struct QUEUE_ITEM *item;  
    struct QUEUE_ITEM *tmp_item;  
  
    TAILQ_INIT(&queue_head);  
    int i=0;  
    for(i=5;i<10;i+=2){  
        item=malloc(sizeof(item));  
        item->value=i;  
        TAILQ_INSERT_TAIL(&queue_head, item, entries);  
    }  
      
    struct QUEUE_ITEM *ins_item;  
    ins_item=malloc(sizeof(ins_item));  
  
    ins_item->value=100;  
    TAILQ_INSERT_BEFORE(item,ins_item,entries);  
  
  
    tmp_item=TAILQ_FIRST(&queue_head);  
    printf("first element is %d/n",tmp_item->value);  
  
    tmp_item=TAILQ_NEXT(tmp_item,entries);  
    printf("next element is %d/n",tmp_item->value);  
  
    tmp_item=TAILQ_NEXT(tmp_item,entries);  
    printf("next element is %d/n",tmp_item->value);  
  
    tmp_item=TAILQ_NEXT(tmp_item,entries);  
    printf("next element is %d/n",tmp_item->value);  
  
}