1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
|
/* ntp_prio_q.c
*
* This file contains the priority queue implementation used by the
* discrete event simulator.
*
* Written By: Sachin Kamboj
* University of Delaware
* Newark, DE 19711
* Copyright (c) 2006
*/
#ifdef HAVE_CONFIG_H
# include <config.h>
#endif
#include <ntp_stdlib.h>
#include <ntp_prio_q.h>
/* Priority Queue
* --------------
* Define a priority queue in which the relative priority of the elements
* is determined by a function 'get_order' which is supplied to the
* priority_queue
*/
queue *debug_create_priority_queue(
q_order_func get_order
#ifdef _CRTDBG_MAP_ALLOC
, const char * sourcefile
, int line_num
#endif
)
{
queue *my_queue;
#ifndef _CRTDBG_MAP_ALLOC
my_queue = emalloc(sizeof(queue));
#else
/* preserve original callsite __FILE__ and __LINE__ for leak report */
my_queue = debug_erealloc(NULL, sizeof(queue), sourcefile, line_num);
#endif
my_queue->get_order = get_order;
my_queue->front = NULL;
my_queue->no_of_elements = 0;
return my_queue;
}
/* Define a function to "destroy" a priority queue, freeing-up
* all the allocated resources in the process
*/
void destroy_queue(
queue *my_queue
)
{
node *temp = NULL;
/* Empty out the queue elements if they are not already empty */
while (my_queue->front != NULL) {
temp = my_queue->front;
my_queue->front = my_queue->front->node_next;
free(temp);
}
/* Now free the queue */
free(my_queue);
}
/* Define a function to allocate memory for one element
* of the queue. The allocated memory consists of size
* bytes plus the number of bytes needed for bookkeeping
*/
void *debug_get_node(
size_t size
#ifdef _CRTDBG_MAP_ALLOC
, const char * sourcefile
, int line_num
#endif
)
{
node *new_node;
#ifndef _CRTDBG_MAP_ALLOC
new_node = emalloc(sizeof(*new_node) + size);
#else
new_node = debug_erealloc(NULL, sizeof(*new_node) + size,
sourcefile, line_num);
#endif
new_node->node_next = NULL;
return new_node + 1;
}
/* Define a function to free the allocated memory for a queue node */
void free_node(
void *my_node
)
{
node *old_node = my_node;
free(old_node - 1);
}
void *
next_node(
void *pv
)
{
node *pn;
pn = pv;
pn--;
if (pn->node_next == NULL)
return NULL;
return pn->node_next + 1;
}
/* Define a function to check if the queue is empty. */
int empty(
queue *my_queue
)
{
return (!my_queue || !my_queue->front);
}
void *
queue_head(
queue *q
)
{
if (NULL == q || NULL == q->front)
return NULL;
return q->front + 1;
}
/* Define a function to add an element to the priority queue.
* The element is added according to its priority -
* relative priority is given by the get_order function
*/
queue *enqueue(
queue * my_queue,
void * my_node
)
{
node *new_node = (node *)my_node - 1;
node *i = NULL;
node *j = my_queue->front;
while (j != NULL &&
(*my_queue->get_order)(new_node + 1, j + 1) > 0) {
i = j;
j = j->node_next;
}
if (i == NULL) { /* Insert at beginning of the queue */
new_node->node_next = my_queue->front;
my_queue->front = new_node;
} else { /* Insert Elsewhere, including the end */
new_node->node_next = i->node_next;
i->node_next = new_node;
}
++my_queue->no_of_elements;
return my_queue;
}
/* Define a function to dequeue the first element from the priority
* queue and return it
*/
void *dequeue(
queue *my_queue
)
{
node *my_node = my_queue->front;
if (my_node != NULL) {
my_queue->front = my_node->node_next;
--my_queue->no_of_elements;
return my_node + 1;
} else
return NULL;
}
/* Define a function that returns the number of elements in the
* priority queue
*/
int get_no_of_elements(
queue *my_queue
)
{
return my_queue->no_of_elements;
}
/* Define a function to append a queue onto another.
* Note: there is a faster way (O(1) as opposed to O(n))
* to do this for simple (FIFO) queues, but we can't rely on
* that for priority queues. (Given the current representation)
*
* I don't anticipate this to be a problem. If it does turn
* out to be a bottleneck, I will consider replacing the
* current implementation with a binomial or fibonacci heap.
*/
void append_queue(
queue *q1,
queue *q2
)
{
while (!empty(q2))
enqueue(q1, dequeue(q2));
destroy_queue(q2);
}
/* FIFO Queue
* ----------
* Use the priority queue to create a traditional FIFO queue.
* The only extra function needed is the create_queue
*/
/* C is not Lisp and does not allow anonymous lambda functions :-(.
* So define a get_fifo_order function here
*/
int get_fifo_order(const void *el1, const void *el2)
{
return 1;
}
|