diff --git a/lib/isc/heap.c b/lib/isc/heap.c index 78b192548a..fd67d7bd78 100644 --- a/lib/isc/heap.c +++ b/lib/isc/heap.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,15 +15,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: heap.c,v 1.28.12.3 2004/03/08 09:04:48 marka Exp $ */ +/* $Id: heap.c,v 1.28.12.4 2006/04/17 18:27:20 explorer Exp $ */ -/* +/*! \file * Heap implementation of priority queues adapted from the following: * - * _Introduction to Algorithms_, Cormen, Leiserson, and Rivest, + * \li "Introduction to Algorithms," Cormen, Leiserson, and Rivest, * MIT Press / McGraw Hill, 1990, ISBN 0-262-03141-8, chapter 7. * - * _Algorithms_, Second Edition, Sedgewick, Addison-Wesley, 1988, + * \li "Algorithms," Second Edition, Sedgewick, Addison-Wesley, 1988, * ISBN 0-201-06673-4, chapter 11. */ @@ -35,20 +35,23 @@ #include /* Required for memcpy. */ #include -/* +/*@{*/ +/*% * Note: to make heap_parent and heap_left easy to compute, the first * element of the heap array is not used; i.e. heap subscripts are 1-based, - * not 0-based. + * not 0-based. The parent is index/2, and the left-child is index*2. + * The right child is index*2+1. */ #define heap_parent(i) ((i) >> 1) #define heap_left(i) ((i) << 1) +/*@}*/ #define SIZE_INCREMENT 1024 #define HEAP_MAGIC ISC_MAGIC('H', 'E', 'A', 'P') #define VALID_HEAP(h) ISC_MAGIC_VALID(h, HEAP_MAGIC) -/* +/*% * When the heap is in a consistent state, the following invariant * holds true: for every element i > 1, heap_parent(i) has a priority * higher than or equal to that of i. @@ -57,6 +60,7 @@ ! heap->compare(heap->array[(i)], \ heap->array[heap_parent(i)])) +/*% ISC heap structure. */ struct isc_heap { unsigned int magic; isc_mem_t * mctx; @@ -141,8 +145,8 @@ static void float_up(isc_heap_t *heap, unsigned int i, void *elt) { unsigned int p; - for (p = heap_parent(i); - i > 1 && heap->compare(elt, heap->array[p]); + for (p = heap_parent(i) ; + i > 1 && heap->compare(elt, heap->array[p]) ; i = p, p = heap_parent(i)) { heap->array[i] = heap->array[p]; if (heap->index != NULL) @@ -196,48 +200,48 @@ isc_heap_insert(isc_heap_t *heap, void *elt) { } void -isc_heap_delete(isc_heap_t *heap, unsigned int i) { +isc_heap_delete(isc_heap_t *heap, unsigned int index) { void *elt; isc_boolean_t less; REQUIRE(VALID_HEAP(heap)); - REQUIRE(i >= 1 && i <= heap->last); + REQUIRE(index >= 1 && index <= heap->last); - if (i == heap->last) { + if (index == heap->last) { heap->last--; } else { elt = heap->array[heap->last--]; - less = heap->compare(elt, heap->array[i]); - heap->array[i] = elt; + less = heap->compare(elt, heap->array[index]); + heap->array[index] = elt; if (less) - float_up(heap, i, heap->array[i]); + float_up(heap, index, heap->array[index]); else - sink_down(heap, i, heap->array[i]); + sink_down(heap, index, heap->array[index]); } } void -isc_heap_increased(isc_heap_t *heap, unsigned int i) { +isc_heap_increased(isc_heap_t *heap, unsigned int index) { REQUIRE(VALID_HEAP(heap)); - REQUIRE(i >= 1 && i <= heap->last); + REQUIRE(index >= 1 && index <= heap->last); - float_up(heap, i, heap->array[i]); + float_up(heap, index, heap->array[index]); } void -isc_heap_decreased(isc_heap_t *heap, unsigned int i) { +isc_heap_decreased(isc_heap_t *heap, unsigned int index) { REQUIRE(VALID_HEAP(heap)); - REQUIRE(i >= 1 && i <= heap->last); + REQUIRE(index >= 1 && index <= heap->last); - sink_down(heap, i, heap->array[i]); + sink_down(heap, index, heap->array[index]); } void * -isc_heap_element(isc_heap_t *heap, unsigned int i) { +isc_heap_element(isc_heap_t *heap, unsigned int index) { REQUIRE(VALID_HEAP(heap)); - REQUIRE(i >= 1 && i <= heap->last); + REQUIRE(index >= 1 && index <= heap->last); - return (heap->array[i]); + return (heap->array[index]); } void @@ -247,6 +251,6 @@ isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap) { REQUIRE(VALID_HEAP(heap)); REQUIRE(action != NULL); - for (i = 1; i <= heap->last; i++) + for (i = 1 ; i <= heap->last ; i++) (action)(heap->array[i], uap); } diff --git a/lib/isc/include/isc/heap.h b/lib/isc/include/isc/heap.h index 5ebf40471e..7c7f3c2916 100644 --- a/lib/isc/include/isc/heap.h +++ b/lib/isc/include/isc/heap.h @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1997-2001 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,36 +15,155 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: heap.h,v 1.16.206.1 2004/03/06 08:14:41 marka Exp $ */ +/* $Id: heap.h,v 1.16.206.2 2006/04/17 18:27:20 explorer Exp $ */ #ifndef ISC_HEAP_H #define ISC_HEAP_H 1 +/*! \file */ + #include #include ISC_LANG_BEGINDECLS -/* +/*% * The comparision function returns ISC_TRUE if the first argument has * higher priority than the second argument, and ISC_FALSE otherwise. */ typedef isc_boolean_t (*isc_heapcompare_t)(void *, void *); +/*% + * The index function allows the client of the heap to receive a callback + * when an item's index number changes. This allows it to maintain + * sync with its external state, but still delete itself, since deletions + * from the heap require the index be provided. + */ typedef void (*isc_heapindex_t)(void *, unsigned int); + +/*% + * The heapaction function is used when iterating over the heap. + * + * NOTE: The heap structure CANNOT BE MODIFIED during the call to + * isc_heap_foreach(). + */ typedef void (*isc_heapaction_t)(void *, void *); typedef struct isc_heap isc_heap_t; -isc_result_t isc_heap_create(isc_mem_t *, isc_heapcompare_t, - isc_heapindex_t, unsigned int, isc_heap_t **); -void isc_heap_destroy(isc_heap_t **); -isc_result_t isc_heap_insert(isc_heap_t *, void *); -void isc_heap_delete(isc_heap_t *, unsigned int); -void isc_heap_increased(isc_heap_t *, unsigned int); -void isc_heap_decreased(isc_heap_t *, unsigned int); -void * isc_heap_element(isc_heap_t *, unsigned int); -void isc_heap_foreach(isc_heap_t *, isc_heapaction_t, void *); +isc_result_t +isc_heap_create(isc_mem_t *mctx, isc_heapcompare_t compare, + isc_heapindex_t index, unsigned int size_increment, + isc_heap_t **heapp); +/*!< + * \brief Create a new heap. The heap is implemented using a space-efficient + * storage method. When the heap elements are deleted space is not freed + * but will be reused when new elements are inserted. + * + * Requires: + *\li "mctx" is valid. + *\li "compare" is a function which takes two void * arguments and + * returns ISC_TRUE if the first argument has a higher priority than + * the second, and ISC_FALSE otherwise. + *\li "index" is a function which takes a void *, and an unsigned int + * argument. This function will be called whenever an element's + * index value changes, so it may continue to delete itself from the + * heap. This option may be NULL if this functionality is unneeded. + *\li "size_increment" is a hint about how large the heap should grow + * when resizing is needed. If this is 0, a default size will be + * used, which is currently 1024, allowing space for an additional 1024 + * heap elements to be inserted before adding more space. + *\li "heapp" is not NULL, and "*heap" is NULL. + * + * Returns: + *\li ISC_R_SUCCESS - success + *\li ISC_R_NOMEMORY - insufficient memory + */ + +void +isc_heap_destroy(isc_heap_t **heapp); +/*!< + * \brief Destroys a heap. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + */ + +isc_result_t +isc_heap_insert(isc_heap_t *heap, void *elt); +/*!< + * \brief Inserts a new element into a heap. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + */ + +void +isc_heap_delete(isc_heap_t *heap, unsigned int index); +/*!< + * \brief Deletes an element from a heap, by element index. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + *\li "index" is a valid element index, as provided by the "index" callback + * provided during heap creation. + */ + +void +isc_heap_increased(isc_heap_t *heap, unsigned int index); +/*!< + * \brief Indicates to the heap that an element's priority has increased. + * This function MUST be called whenever an element has increased in priority. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + *\li "index" is a valid element index, as provided by the "index" callback + * provided during heap creation. + */ + +void +isc_heap_decreased(isc_heap_t *heap, unsigned int index); +/*!< + * \brief Indicates to the heap that an element's priority has decreased. + * This function MUST be called whenever an element has decreased in priority. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + *\li "index" is a valid element index, as provided by the "index" callback + * provided during heap creation. + */ + +void * +isc_heap_element(isc_heap_t *heap, unsigned int index); +/*!< + * \brief Returns the element for a specific element index. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + *\li "index" is a valid element index, as provided by the "index" callback + * provided during heap creation. + * + * Returns: + *\li A pointer to the element for the element index. + */ + +void +isc_heap_foreach(isc_heap_t *heap, isc_heapaction_t action, void *uap); +/*!< + * \brief Iterate over the heap, calling an action for each element. The + * order of iteration is not sorted. + * + * Requires: + *\li "heapp" is not NULL and "*heap" points to a valid isc_heap_t. + *\li "action" is not NULL, and is a function which takes two arguments. + * The first is a void *, representing the element, and the second is + * "uap" as provided to isc_heap_foreach. + *\li "uap" is a caller-provided argument, and may be NULL. + * + * Note: + *\li The heap structure CANNOT be modified during this iteration. The only + * safe function to call while iterating the heap is isc_heap_element(). + */ ISC_LANG_ENDDECLS diff --git a/lib/isc/print.c b/lib/isc/print.c index 6542fe4f19..ee50b29e5d 100644 --- a/lib/isc/print.c +++ b/lib/isc/print.c @@ -1,5 +1,5 @@ /* - * Copyright (C) 2004 Internet Systems Consortium, Inc. ("ISC") + * Copyright (C) 2004-2006 Internet Systems Consortium, Inc. ("ISC") * Copyright (C) 1999-2001, 2003 Internet Software Consortium. * * Permission to use, copy, modify, and distribute this software for any @@ -15,12 +15,15 @@ * PERFORMANCE OF THIS SOFTWARE. */ -/* $Id: print.c,v 1.22.2.3.2.3 2004/03/06 08:14:33 marka Exp $ */ +/* $Id: print.c,v 1.22.2.3.2.4 2006/04/17 18:27:20 explorer Exp $ */ + +/*! \file */ #include #include -#include /* for sprintf */ +#include /* for sprintf() */ +#include /* for strlen() */ #define ISC__PRINT_SOURCE /* Used to get the isc_print_* prototypes. */ @@ -41,7 +44,7 @@ isc_print_sprintf(char *str, const char *format, ...) { return (strlen(str)); } -/* +/*! * Return length of string that would have been written if not truncated. */ @@ -57,7 +60,7 @@ isc_print_snprintf(char *str, size_t size, const char *format, ...) { } -/* +/*! * Return length of string that would have been written if not truncated. */ diff --git a/util/copyrights b/util/copyrights index cb7c70e60d..9a69a4f9ed 100644 --- a/util/copyrights +++ b/util/copyrights @@ -1902,7 +1902,7 @@ ./lib/isc/event.c C 1998,1999,2000,2001,2004 ./lib/isc/fsaccess.c C 2000,2001,2004 ./lib/isc/hash.c C 2003,2004,2006 -./lib/isc/heap.c C 1997,1998,1999,2000,2001,2004 +./lib/isc/heap.c C 1997,1998,1999,2000,2001,2004,2005,2006 ./lib/isc/hex.c C 2000,2001,2002,2003,2004 ./lib/isc/hmacmd5.c C 2000,2001,2004,2006 ./lib/isc/include/.cvsignore X 1999,2000,2001 @@ -1925,7 +1925,7 @@ ./lib/isc/include/isc/formatcheck.h C 2000,2001,2004 ./lib/isc/include/isc/fsaccess.h C 2000,2001,2004 ./lib/isc/include/isc/hash.h C 2003,2004 -./lib/isc/include/isc/heap.h C 1997,1998,1999,2000,2001,2004 +./lib/isc/include/isc/heap.h C 1997,1998,1999,2000,2001,2004,2005,2006 ./lib/isc/include/isc/hex.h C 2000,2001,2004 ./lib/isc/include/isc/hmacmd5.h C 2000,2001,2004 ./lib/isc/include/isc/interfaceiter.h C 1999,2000,2001,2004 @@ -2002,7 +2002,7 @@ ./lib/isc/nothreads/thread.c C 2000,2001,2004 ./lib/isc/ondestroy.c C 2000,2001,2004 ./lib/isc/parseint.c C 2001,2002,2003,2004 -./lib/isc/print.c C 1999,2000,2001,2003,2004 +./lib/isc/print.c C 1999,2000,2001,2003,2004,2005,2006 ./lib/isc/pthreads/.cvsignore X 1999,2000,2001 ./lib/isc/pthreads/Makefile.in MAKE 1998,1999,2000,2001,2004 ./lib/isc/pthreads/condition.c C 1998,1999,2000,2001,2004