99 lines
4.3 KiB
C
99 lines
4.3 KiB
C
|
/****************************************************************
|
||
|
* *
|
||
|
* Copyright 2001, 2011 Fidelity Information Services, Inc *
|
||
|
* *
|
||
|
* This source code contains the intellectual property *
|
||
|
* of its copyright holder(s), and is made available *
|
||
|
* under a license. If you do not know the terms of *
|
||
|
* the license, please stop and do not read further. *
|
||
|
* *
|
||
|
****************************************************************/
|
||
|
|
||
|
#ifndef __BUDDY_LIST_H__
|
||
|
#define __BUDDY_LIST_H__
|
||
|
|
||
|
/* This is a general purpose structure used for storing a list of similar-sized structure-elements with the need for
|
||
|
* efficiently accessing the element once we know its index.
|
||
|
* It maintains an array of pointers "ptrArray".
|
||
|
* The first and second pointers i.e. ptrArray[0] and ptrArray[1] point to an array containing "initAlloc" elements.
|
||
|
* Every other pointer ptrArray[i] points to an array containing double-the-number-of-elements
|
||
|
* as the array pointed to by ptrArray[i-1].
|
||
|
* This also provides for iterating through the list of elements.
|
||
|
*/
|
||
|
|
||
|
typedef struct buddy_list_struct
|
||
|
{
|
||
|
char **ptrArray; /* the array of pointers */
|
||
|
int4 elemSize; /* the size of each structure-element */
|
||
|
int4 initAlloc; /* the number of structures in the ptrArray[0] and ptrArray[1] */
|
||
|
int4 initAllocBits; /* number of bits corresponding to initAlloc */
|
||
|
int4 nElems; /* the current number of elements used up in the total array */
|
||
|
int4 cumulMaxElems; /* the maximum number of elements that can be held from the first upto the current array */
|
||
|
char **ptrArrayCurr; /* = &ptrArray[i] where i is the current array index in use for allocation */
|
||
|
char *nextFreePtr; /* pointer to the next free element in the current array. Initially = ptrArray[0] */
|
||
|
char *free_que; /* pointer to the singly linked list of freed-up elements */
|
||
|
# ifdef DEBUG
|
||
|
/* The following two debug-only variables are present to avoid mixing of usage of the functions "free_last_n_elements"
|
||
|
* and "get_new_free_element"/"free_element()" in the same buddy list. This is because they both use completely
|
||
|
* different schemes to free up elements (one reduces the # of elements in the buddy list whereas the other does not
|
||
|
* touch the # of elements but maintains an internal singly linked list of freed up elements) and they cannot coexist.
|
||
|
*/
|
||
|
boolean_t used_free_last_n_elements; /* TRUE if "free_last_n_elements" was called in this buddy_list */
|
||
|
boolean_t used_free_element; /* TRUE if "get_new_free_element" or "free_element" was called */
|
||
|
# endif
|
||
|
} buddy_list;
|
||
|
|
||
|
void initialize_list(buddy_list *list, int4 elemSize, int4 initAlloc);
|
||
|
char *get_new_element(buddy_list *list, int4 nElements);
|
||
|
char *find_element(buddy_list *list, int4 index);
|
||
|
void cleanup_list(buddy_list *list);
|
||
|
void reinitialize_list(buddy_list *list); /* used for reusing already allocated storage */
|
||
|
boolean_t free_last_n_elements(buddy_list *list, int4 num); /* to free up the last contiguous "num" elements */
|
||
|
void free_element(buddy_list *list, char *elem); /* to free up an element and reuse it later */
|
||
|
char *get_new_free_element(buddy_list *list); /* gets a freed-up element if available otherwise gets a new one */
|
||
|
|
||
|
#define CAREFUL_FREEUP_BUDDY_LIST(list) \
|
||
|
{ \
|
||
|
if (NULL != list) \
|
||
|
FREEUP_BUDDY_LIST(list); \
|
||
|
}
|
||
|
|
||
|
#define FREEUP_BUDDY_LIST(list) \
|
||
|
{ \
|
||
|
assert(list); \
|
||
|
if (NULL != list) \
|
||
|
{ \
|
||
|
cleanup_list(list); \
|
||
|
free(list); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#define VERIFY_LIST_IS_REINITIALIZED(list) \
|
||
|
{ /* The following code verifies the same fields initialized by the \
|
||
|
* function "reinitialize_list". Any changes to one should be reflected \
|
||
|
* in the other. \
|
||
|
*/ \
|
||
|
assert((0 == list->nElems) || process_exiting); \
|
||
|
assert((list->cumulMaxElems == list->initAlloc) || process_exiting); \
|
||
|
assert((list->ptrArrayCurr == list->ptrArray) || process_exiting); \
|
||
|
assert((list->nextFreePtr == list->ptrArray[0])|| process_exiting); \
|
||
|
assert((NULL == list->free_que) || process_exiting); \
|
||
|
}
|
||
|
|
||
|
#define REINITIALIZE_LIST(LST) \
|
||
|
{ \
|
||
|
buddy_list *lcllist; \
|
||
|
\
|
||
|
lcllist = LST; \
|
||
|
assert((NULL == lcllist->free_que) || lcllist->nElems); \
|
||
|
if (lcllist->nElems) \
|
||
|
reinitialize_list(lcllist); \
|
||
|
else \
|
||
|
{ /* No need to reinitialize. Verify \
|
||
|
* that list is already initialized */ \
|
||
|
VERIFY_LIST_IS_REINITIALIZED(lcllist); \
|
||
|
} \
|
||
|
}
|
||
|
|
||
|
#endif
|