File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / ntp / lib / isc / heap.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Tue May 29 12:08:38 2012 UTC (12 years, 7 months ago) by misho
Branches: ntp, MAIN
CVS tags: v4_2_6p5p0, v4_2_6p5, HEAD
ntp 4.2.6p5

    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.1.1.1 2012/05/29 12:08:38 misho 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>