diff options
author | Quincey Koziol <koziol@hdfgroup.org> | 1998-03-17 22:46:27 (GMT) |
---|---|---|
committer | Quincey Koziol <koziol@hdfgroup.org> | 1998-03-17 22:46:27 (GMT) |
commit | 96dd634330502cdde53905c9edbef56028323969 (patch) | |
tree | 18e95df957a1b8b78604016aa8a6108b3c85c10b /src/H5I.c | |
parent | 4494348eb229ae0661754c974695d8a293c6168b (diff) | |
download | hdf5-96dd634330502cdde53905c9edbef56028323969.zip hdf5-96dd634330502cdde53905c9edbef56028323969.tar.gz hdf5-96dd634330502cdde53905c9edbef56028323969.tar.bz2 |
[svn-r324] Change H5A (atoms) to H5I (IDs)
Diffstat (limited to 'src/H5I.c')
-rw-r--r-- | src/H5I.c | 840 |
1 files changed, 840 insertions, 0 deletions
diff --git a/src/H5I.c b/src/H5I.c new file mode 100644 index 0000000..028108f --- /dev/null +++ b/src/H5I.c @@ -0,0 +1,840 @@ +/**************************************************************************** + * NCSA HDF * + * Software Development Group * + * National Center for Supercomputing Applications * + * University of Illinois at Urbana-Champaign * + * 605 E. Springfield, Champaign IL 61820 * + * * + * For conditions of distribution and use, see the accompanying * + * hdf/COPYING file. * + * * + ****************************************************************************/ + +#ifdef RCSID +static char RcsId[] = "@(#)$Revision$"; +#endif + +/* $Id$ */ + +/* + FILE + H5I.c - Internal storage routines for handling "IDs" + + REMARKS + ID's which allow objects (void *'s currently) to be bundled into "groups" + for more general storage. + + DESIGN + The groups are stored in an array of pointers to store each group in an + element. Each "group" node contains a link to a hash table to manage the IDs + in each group. The allowed "groups" are stored in an enum (called group_t) + in H5Ipublic.h. + + BUGS/LIMITATIONS + Can't interate over the IDs in a group. + + LOCAL ROUTINES + H5I_find_id - Returns a pointer to an HAI_id_info_t from an ID + H5I_get_id_node - Gets an ID node (uses the ID free list) + H5I_release_id_node - Releases an ID node (uses the ID free list) + EXPORTED ROUTINES + ID Functions: + H5I_register - Register an object in a group and get an ID for it + H5I_object - Get the object for an ID + H5I_group - Get the group for an ID + H5I_remove - Remove an ID from a group + H5I_search - Search a group for a particular object + ID Group Functions: + H5I_init_group - Initialize a group to store IDs in + H5I_destroy_group - Destroy an ID group + ID Group Cleanup: + H5Ishutdown - Terminate various static buffers. + + AUTHOR + Quincey Koziol + + MODIFICATION HISTORY + 1/3/96 - Starting writing specs & coding prototype + 1/7/96 - Finished coding prototype + 6/10/97 - Moved into HDF5 library + */ + +#include <H5private.h> +#include <H5Iprivate.h> +#include <H5Eprivate.h> +#include <H5MMprivate.h> + +#define PABLO_MASK H5I_mask + +/*-------------------- Locally scoped variables -----------------------------*/ + +#ifdef IDS_ARE_CACHED +/* Array of pointers to ID groups */ +static hid_t H5I_id_cache[ID_CACHE_SIZE] = {-1, -1, -1, -1}; +static void *H5I_obj_cache[ID_CACHE_SIZE]; +#endif + +/* Array of pointers to atomic groups */ +static H5I_id_group_t *id_group_list[MAXGROUP]; + +/* Pointer to the atom node free list */ +static H5I_id_info_t *id_free_list = NULL; + +/* Interface initialialization? */ +static hbool_t interface_initialize_g = FALSE; +#define INTERFACE_INIT H5I_init_interface +static herr_t H5I_init_interface(void); + +/*--------------------- Local function prototypes ---------------------------*/ +static H5I_id_info_t *H5I_find_id(hid_t id); +static H5I_id_info_t *H5I_get_id_node(void); +static herr_t H5I_release_id_node(H5I_id_info_t *id); + + +/*-------------------------------------------------------------------------- +NAME + H5I_init_interface -- Initialize interface-specific information +USAGE + herr_t H5I_init_interface() +RETURNS + SUCCEED/FAIL +DESCRIPTION + Initializes any interface-specific data or routines. +--------------------------------------------------------------------------*/ +static herr_t +H5I_init_interface(void) +{ + herr_t ret_value = SUCCEED; + FUNC_ENTER(H5I_init_interface, FAIL); + + /* Registers the cleanup routine with the exit chain */ + ret_value = H5_add_exit(&H5I_term_interface); + + FUNC_LEAVE(ret_value); +} + + +/****************************************************************************** + NAME + H5I_init_group - Initialize an ID group + + DESCRIPTION + Creates a global ID group to store IDs in. If the group has already + been initialized, this routine just increments the count of # of + initializations and returns without trying to change the size of the hash + table. A specific number of group entries may be reserved to enable + "constant" values to be handed out which are valid IDs in the group, but + which do not map to any data structures and are not allocated dynamicly + later. + + RETURNS + Returns SUCCEED if successful and FAIL otherwise + +******************************************************************************/ +intn +H5I_init_group(H5I_group_t grp, /* IN: Group to initialize */ + intn hash_size, /* IN: Minimum hash table size to use for group */ + uintn reserved, /* IN: Number of hash table entries to reserve */ + herr_t (*free_func) (void *) /* IN: Function to call when releasing ref counted objects */ +) +{ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */ + intn ret_value = SUCCEED; + + FUNC_ENTER(H5I_init_group, FAIL); + + if ((grp <= BADGROUP || grp >= MAXGROUP) && hash_size > 0) { + HGOTO_DONE(FAIL); + } + +#ifdef HASH_SIZE_POWER_2 + /* + * If anyone knows a faster test for a power of two, please change this + * silly code -QAK + */ + if (!(hash_size == 2 || hash_size == 4 || hash_size == 8 || + hash_size == 16 || hash_size == 32 || hash_size == 64 || + hash_size == 128 || hash_size == 256 || hash_size == 512 || + hash_size == 1024 || hash_size == 2048 || hash_size == 4096 || + hash_size == 8192 || hash_size == 16374 || hash_size == 32768 || + hash_size == 65536 || hash_size == 131072 || hash_size == 262144 || + hash_size == 524288 || hash_size == 1048576 || + hash_size == 2097152 || hash_size == 4194304 || + hash_size == 8388608 || hash_size == 16777216 || + hash_size == 33554432 || hash_size == 67108864 || + hash_size == 134217728 || hash_size == 268435456)) + HGOTO_DONE(FAIL); +#endif /* HASH_SIZE_POWER_2 */ + + if (id_group_list[grp] == NULL) { + /* Allocate the group information */ + grp_ptr = H5MM_xcalloc(1, sizeof(H5I_id_group_t)); + id_group_list[grp] = grp_ptr; + } else { + /* Get the pointer to the existing group */ + grp_ptr = id_group_list[grp]; + } + + if (grp_ptr->count == 0) { + /* Initialize the ID group structure */ + grp_ptr->hash_size = hash_size; + grp_ptr->reserved = reserved; + grp_ptr->wrapped = 0; + grp_ptr->ids = 0; + grp_ptr->nextid = reserved; + grp_ptr->free_func = free_func; + grp_ptr->id_list = H5MM_xcalloc(hash_size, sizeof(H5I_id_info_t *)); + } + + /* Increment the count of the times this group has been initialized */ + grp_ptr->count++; + + done: + if (ret_value == FAIL) { + /* Error condition cleanup */ + if (grp_ptr != NULL) { + H5MM_xfree (grp_ptr->id_list); + H5MM_xfree (grp_ptr); + } + } + + /* Normal function cleanup */ + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5I_destroy_group + * + * Purpose: Decrements the reference count on an entire group of IDs. + * If the group reference count becomes zero then the group is + * destroyed along with all atoms in that group regardless of + * their reference counts. Destroying IDs involves calling + * the free-func for each ID's object and then adding the ID + * struct to the ID free list. + * + * Return: Success: SUCCEED + * + * Failure: FAIL + * + * Programmer: Unknown + * + * Modifications: + * + * Robb Matzke, 25 Feb 1998 + * IDs are freed when a group is destroyed. + * + *------------------------------------------------------------------------- + */ +herr_t +H5I_destroy_group(H5I_group_t grp) +{ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the atomic group */ + H5I_id_info_t *cur=NULL, *next=NULL; + intn ret_value = SUCCEED; + intn i; + + FUNC_ENTER(H5I_destroy_group, FAIL); + + if (grp <= BADGROUP || grp >= MAXGROUP) + HGOTO_DONE(FAIL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0) + HGOTO_DONE(FAIL); + + /* + * Decrement the number of users of the atomic group. If this is the + * last user of the group then release all atoms from the group. The + * free function is invoked for each atom being freed. + */ + if ((--(grp_ptr->count)) == 0) { + +#ifdef IDS_ARE_CACHED + /* + * Remove atoms from the global atom cache. + */ + for (i=0; i<ID_CACHE_SIZE; i++) { + if (ID_TO_GROUP(H5I_id_cache[i]) == grp) { + H5I_id_cache[i] = (-1); + H5I_obj_cache[i] = NULL; + } + } +#endif /* IDS_ARE_CACHED */ + + /* + * Free all objects. + */ + if (grp_ptr->free_func) { + for (i=0; i<grp_ptr->hash_size; i++) { + for (cur=grp_ptr->id_list[i]; cur; cur=next) { + /* Free the object */ + (grp_ptr->free_func)(cur->obj_ptr); + + /* Add ID struct to free list */ + next = cur->next; + cur->next = id_free_list; + id_free_list = cur; + } + } + } + + /* Free local cache and reset group */ + H5MM_xfree(grp_ptr->id_list); + HDmemset (grp_ptr, 0, sizeof(grp_ptr)); + } + + done: + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_register - Register an object in a group and get an ID for it. + + DESCRIPTION + Registers an object in a group and returns an ID for it. This routine + does _not_ check for unique-ness of the objects, if you register an object + twice, you will get two different IDs for it. This routine does make + certain that each ID in a group is unique. IDs are created by getting + a unique number for the group the ID is in and incorporating the group + into the ID which is returned to the user. + + RETURNS + Returns ID if successful and FAIL otherwise + +*******************************************************************************/ +hid_t +H5I_register(H5I_group_t grp, /* IN: Group to register the object in */ + void *object /* IN: Object to attach to atom */ +) +{ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the group */ + H5I_id_info_t *id_ptr = NULL; /* ptr to the new ID information */ + hid_t new_id; /* new ID */ + uintn hash_loc; /* new item's hash table location */ + hid_t ret_value = SUCCEED; + + FUNC_ENTER(H5I_register, FAIL); + + if (grp <= BADGROUP || grp >= MAXGROUP) + HGOTO_DONE(FAIL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0) + HGOTO_DONE(FAIL); + + if ((id_ptr = H5I_get_id_node()) == NULL) + HGOTO_DONE(FAIL); + + /* Create the struct & it's ID */ + new_id = MAKE_ID(grp, grp_ptr->nextid); + id_ptr->id = new_id; + id_ptr->count = 1; /*initial reference count*/ + id_ptr->obj_ptr = object; + id_ptr->next = NULL; + + /* hash bucket already full, prepend to front of chain */ + hash_loc = grp_ptr->nextid % (uintn) grp_ptr->hash_size; + if (grp_ptr->id_list[hash_loc] != NULL) + id_ptr->next = grp_ptr->id_list[hash_loc]; + + /* Insert into the group */ + grp_ptr->id_list[hash_loc] = id_ptr; + grp_ptr->ids++; + grp_ptr->nextid++; + + /* + * This next section of code checks for the 'nextid' getting too large and + * wrapping around, thus necessitating checking for duplicate IDs being + * handed out. + */ + if (grp_ptr->nextid > (uintn) ID_MASK || grp_ptr->wrapped != 0) { + if (grp_ptr->wrapped == 0) { + /* set the "wrapped around" flag if it isn't already */ + grp_ptr->wrapped = 1; + /* re-start the ID counter */ + grp_ptr->nextid = grp_ptr->reserved; + } + + do { + /* new ID to check for */ + hid_t next_id = MAKE_ID(grp, grp_ptr->nextid); + H5I_id_info_t *curr_id; /* ptr to the current atom */ + hash_loc = ID_TO_LOC (grp_ptr->nextid, grp_ptr->hash_size); + + curr_id = grp_ptr->id_list[hash_loc]; + if (curr_id == NULL) break; /* Ha! this is not likely... */ + + while (curr_id != NULL) { + if (curr_id->id == next_id) break; + curr_id = curr_id->next; + } + if (curr_id == NULL) break; /* must not have found a match */ + grp_ptr->nextid++; + } while (grp_ptr->nextid <= (uintn) ID_MASK); + + if (grp_ptr->nextid > (uintn) ID_MASK) { + /* All the IDs are gone! */ + HGOTO_DONE(FAIL); + } + } + ret_value = new_id; + + done: + if (ret_value == FAIL) { + /* Error condition cleanup */ + } + + /* Normal function cleanup */ + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_inc_ref - Adds a reference to a reference counted ID. + IN: ID to increment reference count for + DESCRIPTION + Increments the number of references outstanding for an ID. This will + fail if the group is not a reference counted group. + + RETURNS + ID/FAIL + +*******************************************************************************/ +hid_t +H5I_inc_ref(hid_t id) +{ + H5I_group_t grp = ID_TO_GROUP(id); /* object's group */ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the ID group*/ + H5I_id_info_t *id_ptr = NULL; /* ptr to the new ID */ + hid_t ret_value = FAIL; + + FUNC_ENTER(H5I_inc_ref, FAIL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0 || grp_ptr->free_func == NULL) { + HRETURN(FAIL); + } + + /* General lookup of the atom */ + if (NULL!=(id_ptr = H5I_find_id(id))) { + id_ptr->count++; + ret_value = id; + } + + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_object - Returns to the object ptr for the ID + + DESCRIPTION + Retrieves the object ptr which is associated with the ID. + + RETURNS + Returns object ptr if successful and NULL otherwise + +*******************************************************************************/ +void * +H5I_object(hid_t id) +{ +#ifdef IDS_ARE_CACHED + uintn i; /* local counter */ +#endif /* IDS_ARE_CACHED */ + H5I_id_info_t *id_ptr = NULL; /* ptr to the new atom */ + void *ret_value = NULL; + + FUNC_ENTER(H5I_object, NULL); + +#ifdef IDS_ARE_CACHED + /* + * Look for the ID in the cache first. Implement a simple "move + * forward" caching scheme by swapping the found cache item with the + * previous cache item. This gradually migrates used cache items toward + * the front of the cache and unused items toward the end. For instance, + * finding `e' in the cache results in: + * + * Before: a b c d e f g h i j + * | | | X | | | | | + * After: a b c e d f g h i j + */ + for (i=0; i<ID_CACHE_SIZE; i++) + if (H5I_id_cache[i] == id) { + ret_value = H5I_obj_cache[i]; + if (i > 0) { + hid_t t_id = H5I_id_cache[i-1]; + void *t_obj = H5I_obj_cache[i-1]; + H5I_id_cache[i-1] = H5I_id_cache[i]; + H5I_obj_cache[i-1] = H5I_obj_cache[i]; + H5I_id_cache[i] = t_id; + H5I_obj_cache[i] = t_obj; + } + HGOTO_DONE(ret_value); + } +#endif /* IDS_ARE_CACHED */ + + /* General lookup of the ID */ + if ((id_ptr = H5I_find_id(id)) == NULL) HGOTO_DONE(NULL); + + /* Check if we've found the correct ID */ + if (id_ptr != NULL) ret_value = id_ptr->obj_ptr; + + done: + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_group - Returns to the group for the ID + + DESCRIPTION + Retrieves the group which is associated with the ID. + + RETURNS + Returns group if successful and BADGROUP otherwise + +*******************************************************************************/ +H5I_group_t +H5I_group(hid_t id) +{ + H5I_group_t ret_value = BADGROUP; + + FUNC_ENTER(H5I_group, BADGROUP); + + ret_value = ID_TO_GROUP(id); + if (ret_value <= BADGROUP || ret_value >= MAXGROUP) { + HGOTO_DONE(BADGROUP); + } + + + done: + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_remove - Removes an ID from a group + + DESCRIPTION + Removes an ID from a group. + + RETURNS + Returns ID's object if successful and NULL otherwise + +*******************************************************************************/ +void * +H5I_remove(hid_t id) +{ + H5I_id_group_t *grp_ptr = NULL;/* ptr to the atomic group */ + H5I_id_info_t *curr_id, /* ptr to the current atom */ + *last_id; /* ptr to the last atom */ + H5I_group_t grp; /* atom's atomic group */ + uintn hash_loc; /* atom's hash table location */ +#ifdef IDS_ARE_CACHED + uintn i; /* local counting variable */ +#endif + void * ret_value = NULL; + + FUNC_ENTER(H5I_remove, NULL); + + grp = ID_TO_GROUP(id); + if (grp <= BADGROUP || grp >= MAXGROUP) HGOTO_DONE(NULL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0) HGOTO_DONE(NULL); + + /* Get the location in which the ID is located */ + hash_loc = (uintn) ID_TO_LOC(id, grp_ptr->hash_size); + curr_id = grp_ptr->id_list[hash_loc]; + if (curr_id == NULL) HGOTO_DONE(NULL); + + last_id = NULL; + while (curr_id != NULL) { + if (curr_id->id == id) break; + last_id = curr_id; + curr_id = curr_id->next; + } + + if (curr_id != NULL) { + if (last_id == NULL) { + /* ID is the first the chain */ + grp_ptr->id_list[hash_loc] = curr_id->next; + } else { + last_id->next = curr_id->next; + } + ret_value = curr_id->obj_ptr; + H5I_release_id_node(curr_id); + } else { + /* couldn't find the ID in the proper place */ + HGOTO_DONE(NULL); + } + +#ifdef IDS_ARE_CACHED + /* Delete object from cache */ + for (i = 0; i < ID_CACHE_SIZE; i++) + if (H5I_id_cache[i] == id) { + H5I_id_cache[i] = (-1); + H5I_obj_cache[i] = NULL; + break; /* we assume there is only one instance in the cache */ + } +#endif /* IDS_ARE_CACHED */ + + /* Decrement the number of IDs in the group */ + (grp_ptr->ids)--; + + done: + FUNC_LEAVE(ret_value); +} + + +/*------------------------------------------------------------------------- + * Function: H5I_dec_ref + * + * Purpose: Decrements the number of references outstanding for an ID. + * This will fail if the group is not a reference counted group. + * The ID group's 'free' function will be called for the ID + * if the reference count for the ID reaches 0 and a free + * function has been defined at group creation time. + * + * Return: Success: New reference count. + * + * Failure: FAIL + * + * Programmer: Unknown + * + * Modifications: + * + * Robb Matzke, 19 Feb 1998 + * It is no longer an error when the reference count of an item reaches + * zero and no `free' function has been defined. The object is still + * removed from the list. + * + *------------------------------------------------------------------------- + */ +intn +H5I_dec_ref(hid_t id) +{ + H5I_group_t grp = ID_TO_GROUP(id); /* Group the object is in */ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the group */ + H5I_id_info_t *id_ptr = NULL; /* ptr to the new ID */ + void * obj; /* object to call 'free' function with */ + intn ret_value = FAIL; + + FUNC_ENTER(H5I_dec_ref, FAIL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0) { + HRETURN(FAIL); + } + + /* General lookup of the ID */ + if ((id_ptr = H5I_find_id(id)) != NULL) { + /* Decrement the reference count */ + ret_value = --(id_ptr->count); + + /* If the reference count is zero, remove the object from the group */ + if (0 == id_ptr->count && (obj = H5I_remove(id)) != NULL) { + /* + * call the user's 'free' function for the atom's information, + * otherwise just leak memory. + */ + if (grp_ptr->free_func) (grp_ptr->free_func)(obj); + } + ret_value = SUCCEED; + } + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_search - Search for an object in a group and get it's pointer. + + DESCRIPTION + Searchs for an object in a group and returns the pointer to it. + This routine calls the function pointer passed in for each object in the + group until it finds a match. Currently there is no way to resume a + search. + + RETURNS + Returns pointer an ID's object if successful and NULL otherwise + +*******************************************************************************/ +void * +H5I_search(H5I_group_t grp, /* IN: Group to search for the object in */ + H5I_search_func_t func, /* IN: Ptr to the comparison function */ + const void *key /* IN: pointer to key to compare against */ +) +{ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the group */ + H5I_id_info_t *id_ptr = NULL; /* ptr to the new ID */ + intn i; /* local counting variable */ + void * ret_value = NULL; + + FUNC_ENTER(H5I_search, NULL); + + if (grp <= BADGROUP || grp >= MAXGROUP) + HGOTO_DONE(NULL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0) + HGOTO_DONE(NULL); + + /* Start at the beginning of the array */ + for (i = 0; i < grp_ptr->hash_size; i++) { + id_ptr = grp_ptr->id_list[i]; + while (id_ptr != NULL) { + if ((*func) (id_ptr->obj_ptr, key)) + HGOTO_DONE(id_ptr->obj_ptr); /* found the item we are looking for */ + id_ptr = id_ptr->next; + } + } + + done: + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_find_id - Finds a ID in a group + + DESCRIPTION + Retrieves the ID ptr which is associated with the ID. + + RETURNS + Returns ID ptr if successful and NULL otherwise + +*******************************************************************************/ +static H5I_id_info_t * +H5I_find_id(hid_t id) +{ + H5I_id_group_t *grp_ptr = NULL; /* ptr to the group */ + H5I_id_info_t *id_ptr = NULL; /* ptr to the new ID */ + H5I_group_t grp; /* ID's group */ + uintn hash_loc; /* ID's hash table location */ + H5I_id_info_t *ret_value = NULL; + + FUNC_ENTER(H5I_find_id, NULL); + + grp = ID_TO_GROUP(id); + if (grp <= BADGROUP || grp >= MAXGROUP) + HGOTO_DONE(NULL); + + grp_ptr = id_group_list[grp]; + if (grp_ptr == NULL || grp_ptr->count <= 0) + HGOTO_DONE(NULL); + + /* Get the location in which the ID is located */ + hash_loc = (uintn) ID_TO_LOC(id, grp_ptr->hash_size); + id_ptr = grp_ptr->id_list[hash_loc]; + if (id_ptr == NULL) + HGOTO_DONE(NULL); + + while (id_ptr != NULL) { + if (id_ptr->id == id) break; + id_ptr = id_ptr->next; + } + ret_value = id_ptr; + +#ifdef IDS_ARE_CACHED + H5I_id_cache[ID_CACHE_SIZE-1] = id; + H5I_obj_cache[ID_CACHE_SIZE-1] = id_ptr->obj_ptr; +#endif /* IDS_ARE_CACHED */ + + done: + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_get_idm_node - Gets an ID node + + DESCRIPTION + Either gets an ID node from the free list (if there is one available) + or allocate a node. + + RETURNS + Returns ID ptr if successful and NULL otherwise + +*******************************************************************************/ +static H5I_id_info_t * +H5I_get_id_node(void) +{ + H5I_id_info_t *ret_value = NULL; + + FUNC_ENTER(H5I_get_id_node, NULL); + + if (id_free_list != NULL) { + ret_value = id_free_list; + id_free_list = id_free_list->next; + } else { + ret_value = H5MM_xmalloc(sizeof(H5I_id_info_t)); + } + + FUNC_LEAVE(ret_value); +} + +/****************************************************************************** + NAME + H5I_release_id_node - Releases an ID node + + DESCRIPTION + Puts an ID node into the free list + + RETURNS + SUCCEED + +*******************************************************************************/ +static herr_t +H5I_release_id_node(H5I_id_info_t *id) +{ + FUNC_ENTER(H5I_release_id_node, FAIL); + + /* Insert the ID at the beginning of the free list */ + id->next = id_free_list; + id_free_list = id; + + FUNC_LEAVE(SUCCEED); +} + +/*-------------------------------------------------------------------------- + NAME + H5I_term_interface + PURPOSE + Terminate various static buffers. + USAGE + intn H5I_term_interface() + RETURNS + Returns SUCCEED/FAIL + DESCRIPTION + Free various buffers allocated in the H5I routines. + GLOBAL VARIABLES + COMMENTS, BUGS, ASSUMPTIONS + Should only ever be called by the "atexit" function HDFend + EXAMPLES + REVISION LOG +--------------------------------------------------------------------------*/ +void +H5I_term_interface(void) +{ + H5I_id_info_t *curr; + intn i; + + /* Release the free-list if it exists */ + if (id_free_list != NULL) { + while (id_free_list != NULL) { + curr = id_free_list; + id_free_list = id_free_list->next; + HDfree(curr); + } + } + + /* Release all groups */ + for (i = 0; i < (intn) MAXGROUP; i++) { + if (id_group_list[i] != NULL) { + HDfree(id_group_list[i]); + id_group_list[i] = NULL; + } + } +} |