src/core/ngx_queue.c - nginx source code

Functions defined

Source code


  1. /*
  2. * Copyright (C) Igor Sysoev
  3. * Copyright (C) Nginx, Inc.
  4. */


  5. #include <ngx_config.h>
  6. #include <ngx_core.h>


  7. static void ngx_queue_merge(ngx_queue_t *queue, ngx_queue_t *tail,
  8.     ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *));


  9. /*
  10. * find the middle queue element if the queue has odd number of elements
  11. * or the first element of the queue's second part otherwise
  12. */

  13. ngx_queue_t *
  14. ngx_queue_middle(ngx_queue_t *queue)
  15. {
  16.     ngx_queue_t  *middle, *next;

  17.     middle = ngx_queue_head(queue);

  18.     if (middle == ngx_queue_last(queue)) {
  19.         return middle;
  20.     }

  21.     next = ngx_queue_head(queue);

  22.     for ( ;; ) {
  23.         middle = ngx_queue_next(middle);

  24.         next = ngx_queue_next(next);

  25.         if (next == ngx_queue_last(queue)) {
  26.             return middle;
  27.         }

  28.         next = ngx_queue_next(next);

  29.         if (next == ngx_queue_last(queue)) {
  30.             return middle;
  31.         }
  32.     }
  33. }


  34. /* the stable merge sort */

  35. void
  36. ngx_queue_sort(ngx_queue_t *queue,
  37.     ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
  38. {
  39.     ngx_queue_t  *q, tail;

  40.     q = ngx_queue_head(queue);

  41.     if (q == ngx_queue_last(queue)) {
  42.         return;
  43.     }

  44.     q = ngx_queue_middle(queue);

  45.     ngx_queue_split(queue, q, &tail);

  46.     ngx_queue_sort(queue, cmp);
  47.     ngx_queue_sort(&tail, cmp);

  48.     ngx_queue_merge(queue, &tail, cmp);
  49. }


  50. static void
  51. ngx_queue_merge(ngx_queue_t *queue, ngx_queue_t *tail,
  52.     ngx_int_t (*cmp)(const ngx_queue_t *, const ngx_queue_t *))
  53. {
  54.     ngx_queue_t  *q1, *q2;

  55.     q1 = ngx_queue_head(queue);
  56.     q2 = ngx_queue_head(tail);

  57.     for ( ;; ) {
  58.         if (q1 == ngx_queue_sentinel(queue)) {
  59.             ngx_queue_add(queue, tail);
  60.             break;
  61.         }

  62.         if (q2 == ngx_queue_sentinel(tail)) {
  63.             break;
  64.         }

  65.         if (cmp(q1, q2) <= 0) {
  66.             q1 = ngx_queue_next(q1);
  67.             continue;
  68.         }

  69.         ngx_queue_remove(q2);
  70.         ngx_queue_insert_before(q1, q2);

  71.         q2 = ngx_queue_head(tail);
  72.     }
  73. }