pqueue.c 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  1. /*
  2. * Copyright (c) 2023 Agustina Arzille.
  3. *
  4. * This program is free software: you can redistribute it and/or modify
  5. * it under the terms of the GNU General Public License as published by
  6. * the Free Software Foundation, either version 3 of the License, or
  7. * (at your option) any later version.
  8. *
  9. * This program is distributed in the hope that it will be useful,
  10. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  11. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
  12. * GNU General Public License for more details.
  13. *
  14. * You should have received a copy of the GNU General Public License
  15. * along with this program. If not, see <http://www.gnu.org/licenses/>.
  16. *
  17. */
  18. #include <kern/pqueue.h>
  19. void
  20. pqueue_insert (struct pqueue *pq, struct pqueue_node *node)
  21. {
  22. struct pqueue_node *head = pq->head;
  23. if (! head)
  24. { // Empty queue.
  25. node->prev = node->next = node;
  26. pq->head = node;
  27. }
  28. else if (head->prio < node->prio)
  29. { // New node becomes the top.
  30. node->prev = head->prev;
  31. node->next = head;
  32. node->prev->next = node;
  33. node->next->prev = node;
  34. node->next->prio = node->prio - node->next->prio;
  35. pq->head = node;
  36. }
  37. else
  38. { // Find insertion point.
  39. uint32_t prio = head->prio;
  40. while (prio - head->next->prio >= node->prio && head->next != pq->head)
  41. {
  42. head = head->next;
  43. prio -= head->prio;
  44. }
  45. node->prev = head;
  46. node->next = head->next;
  47. node->prev->next = node;
  48. node->next->prev = node;
  49. node->prio = prio - node->prio;
  50. if (node->next != pq->head)
  51. node->next->prio -= node->prio;
  52. }
  53. }
  54. struct pqueue_node*
  55. pqueue_pop (struct pqueue *pq)
  56. {
  57. struct pqueue_node *node = pq->head;
  58. if (! node)
  59. return (node); // Empty queue.
  60. else if (node->next == node)
  61. { // Remove last element.
  62. pq->head = NULL;
  63. return (node);
  64. }
  65. node->prev->next = node->next;
  66. node->next->prev = node->prev;
  67. node->next->prio = node->prio - node->next->prio;
  68. pq->head = node->next;
  69. return (node);
  70. }
  71. void
  72. pqueue_remove (struct pqueue *pq, struct pqueue_node *node)
  73. {
  74. if (!pq->head)
  75. return;
  76. else if (pq->head != node)
  77. {
  78. node->prev->next = node->next;
  79. node->next->prev = node->prev;
  80. if (node->next != pq->head)
  81. node->next->prio += node->prio;
  82. }
  83. else if (node->next == node)
  84. { // Single element queue.
  85. node->next = node->prev = NULL;
  86. pq->head = NULL;
  87. }
  88. else
  89. {
  90. node->prev->next = node->next;
  91. node->next->prev = node->prev;
  92. node->next->prio = node->prio - node->next->prio;
  93. pq->head = node->next;
  94. }
  95. }