3 /* ntp_data_structures.c
5 * This file contains the data structures used by the ntp configuration
6 * code and the discrete event simulator.
8 * Written By: Sachin Kamboj
9 * University of Delaware
15 #include <stdlib.h> /* Needed for malloc */
16 #include "ntp_data_structures.h"
17 #include "ntp_stdlib.h"
21 * Define a priority queue in which the relative priority of the elements
22 * is determined by a function 'get_order' which is supplied to the
27 queue
*create_priority_queue(int (*get_order
)(void *, void *))
29 queue
*my_queue
= (queue
*) emalloc(sizeof(queue
));
30 my_queue
->get_order
= get_order
;
31 my_queue
->front
= NULL
;
32 my_queue
->no_of_elements
= 0;
37 /* Define a function to "destroy" a priority queue, freeing-up
38 * all the allocated resources in the process
41 void destroy_queue(queue
*my_queue
)
45 /* Empty out the queue elements if they are not already empty */
46 while (my_queue
->front
!= NULL
) {
47 temp
= my_queue
->front
;
48 my_queue
->front
= my_queue
->front
->node_next
;
52 /* Now free the queue */
57 /* Define a function to allocate memory for one element
58 * of the queue. The allocated memory consists of size
59 * bytes plus the number of bytes needed for bookkeeping
62 void *get_node(size_t size
)
64 node
*new_node
= emalloc(sizeof(*new_node
) + size
);
65 new_node
->node_next
= NULL
;
69 /* Define a function to free the allocated memory for a queue node */
70 void free_node(void *my_node
)
72 node
*old_node
= my_node
;
87 if (pn
->node_next
== NULL
)
90 return pn
->node_next
+ 1;
94 /* Define a function to check if the queue is empty. */
95 int empty(queue
*my_queue
)
97 return (!my_queue
|| !my_queue
->front
);
106 if (NULL
== q
|| NULL
== q
->front
)
113 /* Define a function to add an element to the priority queue.
114 * The element is added according to its priority -
115 * relative priority is given by the get_order function
117 queue
*enqueue(queue
*my_queue
, void *my_node
)
119 node
*new_node
= ((node
*) my_node
) - 1;
121 node
*j
= my_queue
->front
;
123 while (j
!= NULL
&& ((*my_queue
->get_order
)(new_node
+ 1, j
+ 1) > 0)) {
128 if (i
== NULL
) { /* Insert at beginning of the queue */
129 new_node
->node_next
= my_queue
->front
;
130 my_queue
->front
= new_node
;
132 else { /* Insert Elsewhere, including the end */
133 new_node
->node_next
= i
->node_next
;
134 i
->node_next
= new_node
;
137 ++my_queue
->no_of_elements
;
142 /* Define a function to dequeue the first element from the priority
143 * queue and return it
146 void *dequeue(queue
*my_queue
)
148 node
*my_node
= my_queue
->front
;
149 if (my_node
!= NULL
) {
150 my_queue
->front
= my_node
->node_next
;
151 --my_queue
->no_of_elements
;
152 return (void *)(my_node
+ 1);
158 /* Define a function that returns the number of elements in the
161 int get_no_of_elements(queue
*my_queue
)
163 return my_queue
->no_of_elements
;
166 /* Define a function to append a queue onto another.
167 * Note: there is a faster way (O(1) as opposed to O(n))
168 * to do this for simple (FIFO) queues, but we can't rely on
169 * that for priority queues. (Given the current representation)
171 * I don't anticipate this to be a problem. If it does turn
172 * out to be a bottleneck, I will consider replacing the
173 * current implementation with a binomial or fibonacci heap.
176 void append_queue(queue
*q1
, queue
*q2
)
179 enqueue(q1
, dequeue(q2
));
185 * Use the priority queue to create a traditional FIFO queue.
186 * The only extra function needed is the create_queue
189 /* C is not Lisp and does not allow anonymous lambda functions :-(.
190 * So define a get_fifo_order function here
193 int get_fifo_order(void *el1
, void *el2
)
197 /* Define a function to create a FIFO queue */
199 queue
*create_queue()
200 { return create_priority_queue(get_fifo_order
);