A clone of btpd with my configuration changes.
Vous ne pouvez pas sélectionner plus de 25 sujets Les noms de sujets doivent commencer par une lettre ou un nombre, peuvent contenir des tirets ('-') et peuvent comporter jusqu'à 35 caractères.

153 lignes
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. }