Annotation of embedaddon/ntp/ntpd/ntp_data_structures.c, revision 1.1.1.1

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

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>