Annotation of embedaddon/ntp/lib/isc/heap.c, revision 1.1
1.1 ! misho 1: /*
! 2: * Copyright (C) 2004-2007 Internet Systems Consortium, Inc. ("ISC")
! 3: * Copyright (C) 1997-2001 Internet Software Consortium.
! 4: *
! 5: * Permission to use, copy, modify, and/or distribute this software for any
! 6: * purpose with or without fee is hereby granted, provided that the above
! 7: * copyright notice and this permission notice appear in all copies.
! 8: *
! 9: * THE SOFTWARE IS PROVIDED "AS IS" AND ISC DISCLAIMS ALL WARRANTIES WITH
! 10: * REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
! 11: * AND FITNESS. IN NO EVENT SHALL ISC BE LIABLE FOR ANY SPECIAL, DIRECT,
! 12: * INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
! 13: * LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE
! 14: * OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
! 15: * PERFORMANCE OF THIS SOFTWARE.
! 16: */
! 17:
! 18: /* $Id: heap.c,v 1.37 2007/10/19 17:15:53 explorer Exp $ */
! 19:
! 20: /*! \file
! 21: * Heap implementation of priority queues adapted from the following:
! 22: *
! 23: * \li "Introduction to Algorithms," Cormen, Leiserson, and Rivest,
! 24: * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7.
! 25: *
! 26: * \li "Algorithms," Second Edition, Sedgewick, Addison-Wesley, 1988,
! 27: * ISBN 0-201-06673-4, chapter 11.
! 28: */
! 29:
! 30: #include <config.h>
! 31:
! 32: #include <isc/heap.h>
! 33: #include <isc/magic.h>
! 34: #include <isc/mem.h>
! 35: #include <isc/string.h> /* Required for memcpy. */
! 36: #include <isc/util.h>
! 37:
! 38: /*@{*/
! 39: /*%
! 40: * Note: to make heap_parent and heap_left easy to compute, the first
! 41: * element of the heap array is not used; i.e. heap subscripts are 1-based,
! 42: * not 0-based. The parent is index/2, and the left-child is index*2.
! 43: * The right child is index*2+1.
! 44: */
! 45: #define heap_parent(i) ((i) >> 1)
! 46: #define heap_left(i) ((i) << 1)
! 47: /*@}*/
! 48:
! 49: #define SIZE_INCREMENT 1024
! 50:
! 51: #define HEAP_MAGIC ISC_MAGIC('H', 'E', 'A', 'P')
! 52: #define VALID_HEAP(h) ISC_MAGIC_VALID(h, HEAP_MAGIC)
! 53:
! 54: /*%
! 55: * When the heap is in a consistent state, the following invariant
! 56: * holds true: for every element i > 1, heap_parent(i) has a priority
! 57: * higher than or equal to that of i.
! 58: */
! 59: #define HEAPCONDITION(i) ((i) == 1 || \
! 60: ! heap->compare(heap->array[(i)], \
! 61: heap->array[heap_parent(i)]))
! 62:
! 63: /*% ISC heap structure. */
! 64: struct isc_heap {
! 65: unsigned int magic;
! 66: isc_mem_t * mctx;
! 67: unsigned int size;
! 68: unsigned int size_increment;
! 69: unsigned int last;
! 70: void **array;
! 71: isc_heapcompare_t compare;
! 72: isc_heapindex_t index;
! 73: };
! 74:
! 75: isc_result_t
! 76: isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare,
! 77: isc_heapindex_t index, unsigned int size_increment,
! 78: isc_heap_t **heapp)
! 79: {
! 80: isc_heap_t *heap;
! 81:
! 82: REQUIRE(heapp != NULL && *heapp == NULL);
! 83: REQUIRE(compare != NULL);
! 84:
! 85: heap = isc_mem_get(mctx, sizeof(*heap));
! 86: if (heap == NULL)
! 87: return (ISC_R_NOMEMORY);
! 88: heap->magic = HEAP_MAGIC;
! 89: heap->mctx = mctx;
! 90: heap->size = 0;
! 91: if (size_increment == 0)
! 92: heap->size_increment = SIZE_INCREMENT;
! 93: else
! 94: heap->size_increment = size_increment;
! 95: heap->last = 0;
! 96: heap->array = NULL;
! 97: heap->compare = compare;
! 98: heap->index = index;
! 99:
! 100: *heapp = heap;
! 101:
! 102: return (ISC_R_SUCCESS);
! 103: }
! 104:
! 105: void
! 106: isc_heap_destroy(isc_heap_t **heapp) {
! 107: isc_heap_t *heap;
! 108:
! 109: REQUIRE(heapp != NULL);
! 110: heap = *heapp;
! 111: REQUIRE(VALID_HEAP(heap));
! 112:
! 113: if (heap->array != NULL)
! 114: isc_mem_put(heap->mctx, heap->array,
! 115: heap->size * sizeof(void *));
! 116: heap->magic = 0;
! 117: isc_mem_put(heap->mctx, heap, sizeof(*heap));
! 118:
! 119: *heapp = NULL;
! 120: }
! 121:
! 122: static isc_boolean_t
! 123: resize(isc_heap_t *heap) {
! 124: void **new_array;
! 125: size_t new_size;
! 126:
! 127: REQUIRE(VALID_HEAP(heap));
! 128:
! 129: new_size = heap->size + heap->size_increment;
! 130: new_array = isc_mem_get(heap->mctx, new_size * sizeof(void *));
! 131: if (new_array == NULL)
! 132: return (ISC_FALSE);
! 133: if (heap->array != NULL) {
! 134: memcpy(new_array, heap->array, heap->size * sizeof(void *));
! 135: isc_mem_put(heap->mctx, heap->array,
! 136: heap->size * sizeof(void *));
! 137: }
! 138: heap->size = new_size;
! 139: heap->array = new_array;
! 140:
! 141: return (ISC_TRUE);
! 142: }
! 143:
! 144: static void
! 145: float_up(isc_heap_t *heap, unsigned int i, void *elt) {
! 146: unsigned int p;
! 147:
! 148: for (p = heap_parent(i) ;
! 149: i > 1 && heap->compare(elt, heap->array[p]) ;
! 150: i = p, p = heap_parent(i)) {
! 151: heap->array[i] = heap->array[p];
! 152: if (heap->index != NULL)
! 153: (heap->index)(heap->array[i], i);
! 154: }
! 155: heap->array[i] = elt;
! 156: if (heap->index != NULL)
! 157: (heap->index)(heap->array[i], i);
! 158:
! 159: INSIST(HEAPCONDITION(i));
! 160: }
! 161:
! 162: static void
! 163: sink_down(isc_heap_t *heap, unsigned int i, void *elt) {
! 164: unsigned int j, size, half_size;
! 165: size = heap->last;
! 166: half_size = size / 2;
! 167: while (i <= half_size) {
! 168: /* Find the smallest of the (at most) two children. */
! 169: j = heap_left(i);
! 170: if (j < size && heap->compare(heap->array[j+1],
! 171: heap->array[j]))
! 172: j++;
! 173: if (heap->compare(elt, heap->array[j]))
! 174: break;
! 175: heap->array[i] = heap->array[j];
! 176: if (heap->index != NULL)
! 177: (heap->index)(heap->array[i], i);
! 178: i = j;
! 179: }
! 180: heap->array[i] = elt;
! 181: if (heap->index != NULL)
! 182: (heap->index)(heap->array[i], i);
! 183:
! 184: INSIST(HEAPCONDITION(i));
! 185: }
! 186:
! 187: isc_result_t
! 188: isc_heap_insert(isc_heap_t *heap, void *elt) {
! 189: unsigned int i;
! 190:
! 191: REQUIRE(VALID_HEAP(heap));
! 192:
! 193: i = ++heap->last;
! 194: if (heap->last >= heap->size && !resize(heap))
! 195: return (ISC_R_NOMEMORY);
! 196:
! 197: float_up(heap, i, elt);
! 198:
! 199: return (ISC_R_SUCCESS);
! 200: }
! 201:
! 202: void
! 203: isc_heap_delete(isc_heap_t *heap, unsigned int index) {
! 204: void *elt;
! 205: isc_boolean_t less;
! 206:
! 207: REQUIRE(VALID_HEAP(heap));
! 208: REQUIRE(index >= 1 && index <= heap->last);
! 209:
! 210: if (index == heap->last) {
! 211: heap->array[heap->last] = NULL;
! 212: heap->last--;
! 213: } else {
! 214: elt = heap->array[heap->last];
! 215: heap->array[heap->last] = NULL;
! 216: heap->last--;
! 217:
! 218: less = heap->compare(elt, heap->array[index]);
! 219: heap->array[index] = elt;
! 220: if (less)
! 221: float_up(heap, index, heap->array[index]);
! 222: else
! 223: sink_down(heap, index, heap->array[index]);
! 224: }
! 225: }
! 226:
! 227: void
! 228: isc_heap_increased(isc_heap_t *heap, unsigned int index) {
! 229: REQUIRE(VALID_HEAP(heap));
! 230: REQUIRE(index >= 1 && index <= heap->last);
! 231:
! 232: float_up(heap, index, heap->array[index]);
! 233: }
! 234:
! 235: void
! 236: isc_heap_decreased(isc_heap_t *heap, unsigned int index) {
! 237: REQUIRE(VALID_HEAP(heap));
! 238: REQUIRE(index >= 1 && index <= heap->last);
! 239:
! 240: sink_down(heap, index, heap->array[index]);
! 241: }
! 242:
! 243: void *
! 244: isc_heap_element(isc_heap_t *heap, unsigned int index) {
! 245: REQUIRE(VALID_HEAP(heap));
! 246: REQUIRE(index >= 1);
! 247:
! 248: if (index <= heap->last)
! 249: return (heap->array[index]);
! 250: return (NULL);
! 251: }
! 252:
! 253: void
! 254: isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap) {
! 255: unsigned int i;
! 256:
! 257: REQUIRE(VALID_HEAP(heap));
! 258: REQUIRE(action != NULL);
! 259:
! 260: for (i = 1 ; i <= heap->last ; i++)
! 261: (action)(heap->array[i], uap);
! 262: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>