text: 
  /*
   * Copyright (C) Igor Sysoev
   * Copyright (C) Nginx, Inc.
   */
  
  
  #include <ngx_config.h>
  #include <ngx_core.h>
  
  
  #ifndef _NGX_QUEUE_H_INCLUDED_
  #define _NGX_QUEUE_H_INCLUDED_
  
  
  typedef struct ngx_queue_s  ngx_queue_t;
  
  struct ngx_queue_s {
      ngx_queue_t  *prev;
      ngx_queue_t  *next;
  };
  
  // 队列数据格式:
  //
  //  Element
  //      UserData
  //      ngx_queue_s
  //        ngx_queue_t  *prev;
  //        ngx_queue_t  *next;
  //
  // 对于队列: UserData是不可见的，所有的next, prev都是ngx_queue_t部分的信息，
  // 为了获取UserData 需要从: prev开始的字段 - offset, 例如: ngx_queue_data
  //
  #define ngx_queue_init(q)                                                     \
      (q)->prev = q;                                                            \
      (q)->next = q
  
  
  #define ngx_queue_empty(h)                                                    \
      (h == (h)->prev)
  
  
  #define ngx_queue_insert_head(h, x)                                           \
      (x)->next = (h)->next;                                                    \
      (x)->next->prev = x;                                                      \
      (x)->prev = h;                                                            \
      (h)->next = x
  
  
  #define ngx_queue_insert_after   ngx_queue_insert_head
  
  // 
  // 队列如何添加元素, 将x添加到队列(以sentinel h来表示)
  //
  #define ngx_queue_insert_tail(h, x)                                           \
      (x)->prev = (h)->prev;                                                    \
      (x)->prev->next = x;                                                      \
      (x)->next = h;                                                            \
      (h)->prev = x
  
  
  #define ngx_queue_head(h)                                                     \
      (h)->next
  
  
  #define ngx_queue_last(h)                                                     \
      (h)->prev
  
  
  #define ngx_queue_sentinel(h)                                                 \
      (h)
  
  
  #define ngx_queue_next(q)                                                     \
      (q)->next
  
  
  #define ngx_queue_prev(q)                                                     \
      (q)->prev
  
  
  #if (NGX_DEBUG)
  
  #define ngx_queue_remove(x)                                                   \
      (x)->next->prev = (x)->prev;                                              \
      (x)->prev->next = (x)->next;                                              \
      (x)->prev = NULL;                                                         \
      (x)->next = NULL
  
  #else
  
  #define ngx_queue_remove(x)                                                   \
      (x)->next->prev = (x)->prev;                                              \
      (x)->prev->next = (x)->next
  
  #endif
  
  
  #define ngx_queue_split(h, q, n)                                              \
      (n)->prev = (h)->prev;                                                    \
      (n)->prev->next = n;                                                      \
      (n)->next = q;                                                            \
      (h)->prev = (q)->prev;                                                    \
      (h)->prev->next = h;                                                      \
      (q)->prev = n;
  
  
  #define ngx_queue_add(h, n)                                                   \
      (h)->prev->next = (n)->next;                                              \
      (n)->next->prev = (h)->prev;                                              \
      (h)->prev = (n)->prev;                                                    \
      (h)->prev->next = h;
  
  
  #define ngx_queue_data(q, type, link)                                         \
      (type *) ((u_char *) q - offsetof(type, link))
  
  
  ngx_queue_t *ngx_queue_middle(ngx_queue_t *queue);
  void ngx_queue_sort(ngx_queue_t *queue,
      ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *));
  
  
  #endif /* _NGX_QUEUE_H_INCLUDED_ */
  