summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--release_docs/RELEASE.txt6
-rw-r--r--src/H5I.c76
2 files changed, 72 insertions, 10 deletions
diff --git a/release_docs/RELEASE.txt b/release_docs/RELEASE.txt
index e5b8c8b..0ee5583 100644
--- a/release_docs/RELEASE.txt
+++ b/release_docs/RELEASE.txt
@@ -117,6 +117,12 @@ Bug Fixes since HDF5-1.8.4
Library
-------
+ - Added a mechanism to the H5I interface to save returned object ID
+ structures for immediate re-use if needed. This addresses a
+ potential performance issue by delaying the case when the next ID to be
+ registered has grown so large that it wraps around and needs to be
+ checked to see if it is available for distribution.
+ (MAM - 2010/03/15 - 1730)
- Files can now be concurrently opened more than once using the core file
driver, as long as the backing store is used. (NAF - 2010/03/09)
- Added support for H5O_COPY_EXPAND_EXT_LINK_FLAG to H5Ocopy. External
diff --git a/src/H5I.c b/src/H5I.c
index c986f1c..37859ee 100644
--- a/src/H5I.c
+++ b/src/H5I.c
@@ -62,6 +62,10 @@
/* Local Macros */
+/* Define the maximum number of returned ID structures to keep around
+ for re-use. */
+#define MAX_FREE_ID_STRUCTS 1000
+
/*
* Define the following macro for fast hash calculations (but limited
* hash sizes)
@@ -99,12 +103,14 @@ typedef struct H5I_id_info_t {
/* ID type structure used */
typedef struct {
unsigned count; /*# of times this type has been initialized*/
+ unsigned free_count; /* # of available ID structures awaiting recycling */
unsigned reserved; /*# of IDs to reserve for constant IDs */
unsigned wrapped; /*whether the id count has wrapped around */
size_t hash_size; /*sizeof the hash table to store the IDs in */
unsigned ids; /*current number of IDs held */
unsigned nextid; /*ID to use for the next atom */
H5I_free_t free_func; /*release object method */
+ H5I_id_info_t * next_id_ptr; /* pointer to head of available ID list */
H5I_id_info_t **id_list; /*pointer to an array of ptrs to IDs */
} H5I_id_type_t;
@@ -832,7 +838,6 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
{
H5I_id_type_t *type_ptr; /*ptr to the type */
H5I_id_info_t *id_ptr; /*ptr to the new ID information */
- hid_t new_id; /*new ID */
unsigned hash_loc; /*new item's hash table location*/
hid_t next_id; /*next ID to check */
H5I_id_info_t *curr_id; /*ptr to the current atom */
@@ -847,26 +852,49 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
type_ptr = H5I_id_type_list_g[type];
if(NULL == type_ptr || type_ptr->count <= 0)
HGOTO_ERROR(H5E_ATOM, H5E_BADGROUP, FAIL, "invalid type")
- if(NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t)))
- HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed")
- /* Create the struct & it's ID */
- new_id = H5I_MAKE(type, type_ptr->nextid);
- id_ptr->id = new_id;
+ /* If there is an available ID structure, use it. */
+ if (type_ptr->next_id_ptr) {
+
+ /* Use existing available ID struct */
+ id_ptr = type_ptr->next_id_ptr;
+
+ /* Remove struct from list of available ones */
+ type_ptr->next_id_ptr = type_ptr->next_id_ptr->next;
+
+ /* Decrease count of available ID structures */
+ type_ptr->free_count--;
+
+ /* If no available ID structure, then create a new id for use, and
+ * allocate a new struct to house it. */
+ } else {
+
+ /* Allocate new ID struct */
+ if(NULL == (id_ptr = H5FL_MALLOC(H5I_id_info_t)))
+ HGOTO_ERROR(H5E_ATOM, H5E_NOSPACE, FAIL, "memory allocation failed")
+
+ /* Make a new ID */
+ id_ptr->id = H5I_MAKE(type, type_ptr->nextid);
+
+ /* Increment nextid value */
+ type_ptr->nextid++;
+
+ } /* end if */
+
+ /* Fill in remaining fields of ID struct */
id_ptr->count = 1; /*initial reference count*/
id_ptr->app_count = !!app_ref;
id_ptr->obj_ptr = object;
id_ptr->next = NULL;
/* hash bucket already full, prepend to front of chain */
- hash_loc = type_ptr->nextid % (unsigned)type_ptr->hash_size;
+ hash_loc = id_ptr->id % (unsigned)type_ptr->hash_size;
if(type_ptr->id_list[hash_loc] != NULL)
id_ptr->next = type_ptr->id_list[hash_loc];
/* Insert into the type */
type_ptr->id_list[hash_loc] = id_ptr;
type_ptr->ids++;
- type_ptr->nextid++;
/*
* This next section of code checks for the 'nextid' getting too large and
@@ -917,7 +945,7 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
} /* end if */
/* Set return value */
- ret_value = new_id;
+ ret_value = id_ptr->id;
done:
FUNC_LEAVE_NOAPI(ret_value)
@@ -1251,6 +1279,7 @@ H5I_remove(hid_t id)
H5I_id_type_t *type_ptr; /*ptr to the atomic type */
H5I_id_info_t *curr_id; /*ptr to the current atom */
H5I_id_info_t *last_id; /*ptr to the last atom */
+ H5I_id_info_t *tmp_id_ptr; /*temp ptr to next atom */
H5I_type_t type; /*atom's atomic type */
unsigned hash_loc; /*atom's hash table location */
void * ret_value = NULL; /*return value */
@@ -1288,7 +1317,17 @@ H5I_remove(hid_t id)
}
/* (Casting away const OK -QAK) */
ret_value = (void *)curr_id->obj_ptr;
- (void)H5FL_FREE(H5I_id_info_t, curr_id);
+
+ /* If there's room, save the struct (and its ID) for future re-use */
+ if (type_ptr->free_count < MAX_FREE_ID_STRUCTS) {
+ curr_id->next = type_ptr->next_id_ptr;
+ type_ptr->next_id_ptr = curr_id;
+ type_ptr->free_count++;
+ /* Otherwise, just toss it. */
+ } else {
+ (void)H5FL_FREE(H5I_id_info_t, curr_id);
+ } /* end if */
+
} else {
/* couldn't find the ID in the proper place */
HGOTO_ERROR(H5E_ATOM, H5E_BADATOM, NULL, "invalid ID")
@@ -1297,6 +1336,23 @@ H5I_remove(hid_t id)
/* Decrement the number of IDs in the type */
(type_ptr->ids)--;
+ /* If there are no more IDs of this type, then we can free all available
+ ID strutures, and reset starting typeid and wrapped status. */
+ if (type_ptr->ids == 0) {
+
+ while (type_ptr->next_id_ptr) {
+
+ tmp_id_ptr = type_ptr->next_id_ptr->next;
+ (void)H5FL_FREE(H5I_id_info_t, type_ptr->next_id_ptr);
+ type_ptr->next_id_ptr = tmp_id_ptr;
+
+ } /* end while */
+
+ type_ptr->nextid = type_ptr->reserved;
+ type_ptr->wrapped = FALSE;
+
+ } /* end if */
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_remove() */