A clone of btpd with my configuration changes.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

153 lines
2.6 KiB

  1. #include <sys/time.h>
  2. #include <assert.h>
  3. #include <stdlib.h>
  4. #include "timeheap.h"
  5. struct th_entry {
  6. struct timespec t;
  7. struct th_handle *h;
  8. };
  9. static struct th_entry *heap;
  10. static int heap_cap;
  11. static int heap_use;
  12. static int
  13. cmptime_lt(struct timespec a, struct timespec b)
  14. {
  15. if (a.tv_sec == b.tv_sec)
  16. return a.tv_nsec < b.tv_nsec;
  17. else
  18. return a.tv_sec < b.tv_sec;
  19. }
  20. static int
  21. cmpentry_lt(int a, int b)
  22. {
  23. return cmptime_lt(heap[a].t, heap[b].t);
  24. }
  25. static void
  26. swap(int i, int j)
  27. {
  28. struct th_entry tmp = heap[i];
  29. heap[i] = heap[j];
  30. heap[i].h->i = i;
  31. heap[j] = tmp;
  32. heap[j].h->i = j;
  33. }
  34. static void
  35. bubble_up(int i)
  36. {
  37. while (i != 0) {
  38. int p = (i-1)/2;
  39. if (cmpentry_lt(i, p)) {
  40. swap(i, p);
  41. i = p;
  42. } else
  43. return;
  44. }
  45. }
  46. static void
  47. bubble_down(int i)
  48. {
  49. int li, ri, ci;
  50. loop:
  51. li = 2*i+1;
  52. ri = 2*i+2;
  53. if (ri < heap_use)
  54. ci = cmpentry_lt(li, ri) ? li : ri;
  55. else if (li < heap_use)
  56. ci = li;
  57. else
  58. return;
  59. if (cmpentry_lt(ci, i)) {
  60. swap(i, ci);
  61. i = ci;
  62. goto loop;
  63. }
  64. }
  65. int
  66. timeheap_init(void)
  67. {
  68. heap_cap = 10;
  69. heap_use = 0;
  70. if ((heap = malloc(sizeof(struct th_entry) * heap_cap)) == NULL)
  71. return -1;
  72. else
  73. return 0;
  74. }
  75. int
  76. timeheap_size(void)
  77. {
  78. return heap_use;
  79. }
  80. int
  81. timeheap_insert(struct th_handle *h, struct timespec *t)
  82. {
  83. if (heap_use == heap_cap) {
  84. int ncap = heap_cap * 2;
  85. struct th_entry *nheap = realloc(heap, ncap * sizeof(struct th_entry));
  86. if (nheap == NULL)
  87. return -1;
  88. heap_cap = ncap;
  89. heap = nheap;
  90. }
  91. heap[heap_use].t = *t;
  92. heap[heap_use].h = h;
  93. h->i = heap_use;
  94. heap_use++;
  95. bubble_up(h->i);
  96. return 0;
  97. }
  98. void
  99. timeheap_remove(struct th_handle *h)
  100. {
  101. assert(h->i >= 0 && h->i < heap_use);
  102. heap_use--;
  103. if (heap_use > 0) {
  104. int i = h->i;
  105. int earlier = cmpentry_lt(heap_use, i);
  106. heap[i] = heap[heap_use];
  107. heap[i].h->i = i;
  108. if (earlier)
  109. bubble_up(i);
  110. else
  111. bubble_down(i);
  112. }
  113. }
  114. void
  115. timeheap_change(struct th_handle *h, struct timespec *t)
  116. {
  117. assert(h->i >= 0 && h->i < heap_use);
  118. int earlier = cmptime_lt(*t, heap[h->i].t);
  119. heap[h->i].t = *t;
  120. if (earlier)
  121. bubble_up(h->i);
  122. else
  123. bubble_down(h->i);
  124. }
  125. struct timespec
  126. timeheap_top(void)
  127. {
  128. return heap[0].t;
  129. }
  130. void *
  131. timeheap_remove_top(void)
  132. {
  133. void *ret = heap[0].h->data;
  134. struct th_handle h = { 0, NULL };
  135. timeheap_remove(&h);
  136. return ret;
  137. }