summaryrefslogtreecommitdiffstats
path: root/src/H5Iint.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/H5Iint.c')
-rw-r--r--src/H5Iint.c235
1 files changed, 203 insertions, 32 deletions
diff --git a/src/H5Iint.c b/src/H5Iint.c
index b511cb5..4d7c076 100644
--- a/src/H5Iint.c
+++ b/src/H5Iint.c
@@ -367,27 +367,52 @@ H5I__clear_type_cb(void *_info, void H5_ATTR_UNUSED *key, void *_udata)
* one and forcing is off.
*/
if (udata->force || (info->count - (!udata->app_ref * info->app_count)) <= 1) {
- /* Check for a 'free' function and call it, if it exists */
+ /* Check if this is an un-realized future object */
H5_GCC_DIAG_OFF("cast-qual")
- if (udata->type_info->cls->free_func &&
- (udata->type_info->cls->free_func)((void *)info->object, H5_REQUEST_NULL) < 0) { /* (Casting away const OK -QAK) */
- if (udata->force) {
+ if (info->is_future) {
+ /* Discard the future object */
+ if ((info->discard_cb)((void *)info->object) < 0) {
+ if (udata->force) {
#ifdef H5I_DEBUG
- if (H5DEBUG(I)) {
- HDfprintf(H5DEBUG(I),
- "H5I: free type=%d obj=0x%08lx "
- "failure ignored\n",
- (int)udata->type_info->cls->type, (unsigned long)(info->object));
- }
+ if (H5DEBUG(I)) {
+ HDfprintf(H5DEBUG(I),
+ "H5I: discard type=%d obj=0x%08lx "
+ "failure ignored\n",
+ (int)udata->type_info->cls->type, (unsigned long)(info->object));
+ }
#endif /* H5I_DEBUG */
+ /* Indicate node should be removed from list */
+ ret_value = TRUE;
+ }
+ }
+ else {
/* Indicate node should be removed from list */
ret_value = TRUE;
}
}
else {
- /* Indicate node should be removed from list */
- ret_value = TRUE;
+ /* Check for a 'free' function and call it, if it exists */
+ if (udata->type_info->cls->free_func &&
+ (udata->type_info->cls->free_func)((void *)info->object, H5_REQUEST_NULL) < 0) {
+ if (udata->force) {
+#ifdef H5I_DEBUG
+ if (H5DEBUG(I)) {
+ HDfprintf(H5DEBUG(I),
+ "H5I: free type=%d obj=0x%08lx "
+ "failure ignored\n",
+ (int)udata->type_info->cls->type, (unsigned long)(info->object));
+ }
+#endif /* H5I_DEBUG */
+
+ /* Indicate node should be removed from list */
+ ret_value = TRUE;
+ }
+ }
+ else {
+ /* Indicate node should be removed from list */
+ ret_value = TRUE;
+ }
}
H5_GCC_DIAG_ON("cast-qual")
@@ -435,10 +460,9 @@ H5I__destroy_type(H5I_type_t type)
if (type_info == NULL || type_info->init_count <= 0)
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, FAIL, "invalid type")
- /* Close/clear/destroy all IDs for this type */
- H5E_BEGIN_TRY {
- H5I_clear_type(type, TRUE, FALSE);
- } H5E_END_TRY /* don't care about errors */
+ /* Close/clear/destroy all IDs for this type */
+ H5E_BEGIN_TRY { H5I_clear_type(type, TRUE, FALSE); }
+ H5E_END_TRY /* don't care about errors */
/* Check if we should release the ID class */
if (type_info->cls->flags & H5I_CLASS_IS_APPLICATION)
@@ -457,30 +481,34 @@ done:
} /* end H5I__destroy_type() */
/*-------------------------------------------------------------------------
- * Function: H5I_register
+ * Function: H5I__register
*
* Purpose: Registers an OBJECT in a TYPE 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
* type is unique. IDs are created by getting a unique number
- * for the type the ID is in and incorporating the type into
+ * for the type the ID is in and incorporating the TYPE into
* the ID which is returned to the user.
*
+ * IDs are marked as "future" if the realize_cb and discard_cb
+ * parameters are non-NULL.
+ *
* Return: Success: New object ID
* Failure: H5I_INVALID_HID
*
*-------------------------------------------------------------------------
*/
hid_t
-H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
+H5I__register(H5I_type_t type, const void *object, hbool_t app_ref, H5I_future_realize_func_t realize_cb,
+ H5I_future_discard_func_t discard_cb)
{
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
H5I_id_info_t * info = NULL; /* Pointer to the new ID information */
hid_t new_id = H5I_INVALID_HID; /* New ID */
hid_t ret_value = H5I_INVALID_HID; /* Return value */
- FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+ FUNC_ENTER_PACKAGE
/* Check arguments */
if (type <= H5I_BADID || (int)type >= H5I_next_type_g)
@@ -488,15 +516,18 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
type_info = H5I_type_info_array_g[type];
if ((NULL == type_info) || (type_info->init_count <= 0))
HGOTO_ERROR(H5E_ID, H5E_BADGROUP, H5I_INVALID_HID, "invalid type")
- if (NULL == (info = H5FL_MALLOC(H5I_id_info_t)))
+ if (NULL == (info = H5FL_CALLOC(H5I_id_info_t)))
HGOTO_ERROR(H5E_ID, H5E_NOSPACE, H5I_INVALID_HID, "memory allocation failed")
/* Create the struct & its ID */
- new_id = H5I_MAKE(type, type_info->nextid);
- info->id = new_id;
- info->count = 1; /* initial reference count */
- info->app_count = !!app_ref;
- info->object = object;
+ new_id = H5I_MAKE(type, type_info->nextid);
+ info->id = new_id;
+ info->count = 1; /* initial reference count */
+ info->app_count = !!app_ref;
+ info->object = object;
+ info->is_future = (NULL != realize_cb);
+ info->realize_cb = realize_cb;
+ info->discard_cb = discard_cb;
/* Insert into the type */
if (H5SL_insert(type_info->ids, info, &info->id) < 0)
@@ -515,6 +546,35 @@ H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
done:
FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I__register() */
+
+/*-------------------------------------------------------------------------
+ * Function: H5I_register
+ *
+ * Purpose: Library-private wrapper for H5I__register.
+ *
+ * Return: Success: New object ID
+ * Failure: H5I_INVALID_HID
+ *
+ *-------------------------------------------------------------------------
+ */
+hid_t
+H5I_register(H5I_type_t type, const void *object, hbool_t app_ref)
+{
+ hid_t ret_value = H5I_INVALID_HID; /* Return value */
+
+ FUNC_ENTER_NOAPI(H5I_INVALID_HID)
+
+ /* Sanity checks */
+ HDassert(type >= H5I_FILE && type < H5I_NTYPES);
+ HDassert(object);
+
+ /* Retrieve ID for object */
+ if (H5I_INVALID_HID == (ret_value = H5I__register(type, object, app_ref, NULL, NULL)))
+ HGOTO_ERROR(H5E_ID, H5E_CANTREGISTER, H5I_INVALID_HID, "unable to register object")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I_register() */
/*-------------------------------------------------------------------------
@@ -566,7 +626,7 @@ H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, h
HGOTO_ERROR(H5E_ID, H5E_BADRANGE, FAIL, "invalid type for provided ID")
/* Allocate new structure to house this ID */
- if (NULL == (info = H5FL_MALLOC(H5I_id_info_t)))
+ if (NULL == (info = H5FL_CALLOC(H5I_id_info_t)))
HGOTO_ERROR(H5E_ID, H5E_NOSPACE, FAIL, "memory allocation failed")
/* Create the struct & insert requested ID */
@@ -574,6 +634,12 @@ H5I_register_using_existing_id(H5I_type_t type, void *object, hbool_t app_ref, h
info->count = 1; /* initial reference count*/
info->app_count = !!app_ref;
info->object = object;
+ /* This API call is only used by the native VOL connector, which is
+ * not asynchronous.
+ */
+ info->is_future = FALSE;
+ info->realize_cb = NULL;
+ info->discard_cb = NULL;
/* Insert into the type */
if (H5SL_insert(type_info->ids, info, &info->id) < 0)
@@ -892,8 +958,7 @@ done:
/*-------------------------------------------------------------------------
* Function: H5I__dec_ref
*
- * Purpose: Decrements the number of references outstanding for an ID.
- * This will fail if the type is not a reference counted type.
+ * Purpose: This will fail if the type is not a reference counted type.
* The ID type'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 type creation time.
@@ -1071,6 +1136,41 @@ done:
} /* end H5I_dec_app_ref() */
/*-------------------------------------------------------------------------
+ * Function: H5I_dec_app_ref_async
+ *
+ * Purpose: Asynchronous wrapper for case of modifying the application ref.
+ * count for an ID as well as normal reference count.
+ *
+ * Note: Allows for asynchronous 'close' operation on object, with
+ * token != H5_REQUEST_NULL.
+ *
+ * Return: Success: New app. reference count
+ * Failure: -1
+ *
+ * Programmer: Houjun Tang
+ * Oct 21, 2019
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5I_dec_app_ref_async(hid_t id, void **token)
+{
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI((-1))
+
+ /* Sanity check */
+ HDassert(id >= 0);
+
+ /* [Possibly] aynchronously decrement refcount on ID */
+ if ((ret_value = H5I__dec_app_ref(id, token)) < 0)
+ HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't asynchronously decrement ID ref count")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_dec_app_ref_async() */
+
+/*-------------------------------------------------------------------------
* Function: H5I__dec_app_ref_always_close
*
* Purpose: Wrapper for case of always closing the ID, even when the free
@@ -1144,6 +1244,38 @@ done:
} /* end H5I_dec_app_ref_always_close() */
/*-------------------------------------------------------------------------
+ * Function: H5I_dec_app_ref_always_close_async
+ *
+ * Purpose: Asynchronous wrapper for case of always closing the ID, even
+ * when the free routine fails
+ *
+ * Note: Allows for asynchronous 'close' operation on object, with
+ * token != H5_REQUEST_NULL.
+ *
+ * Return: Success: New app. reference count
+ * Failure: -1
+ *
+ *-------------------------------------------------------------------------
+ */
+int
+H5I_dec_app_ref_always_close_async(hid_t id, void **token)
+{
+ int ret_value = 0; /* Return value */
+
+ FUNC_ENTER_NOAPI((-1))
+
+ /* Sanity check */
+ HDassert(id >= 0);
+
+ /* [Possibly] aynchronously decrement refcount on ID */
+ if ((ret_value = H5I__dec_app_ref_always_close(id, token)) < 0)
+ HGOTO_ERROR(H5E_ID, H5E_CANTDEC, (-1), "can't asynchronously decrement ID ref count")
+
+done:
+ FUNC_LEAVE_NOAPI(ret_value)
+} /* end H5I_dec_app_ref_always_close_async() */
+
+/*-------------------------------------------------------------------------
* Function: H5I_inc_ref
*
* Purpose: Increment the reference count for an object.
@@ -1455,6 +1587,7 @@ H5I__find_id(hid_t id)
{
H5I_type_t type; /* ID's type */
H5I_type_info_t *type_info = NULL; /* Pointer to the type */
+ H5I_id_info_t * id_info = NULL; /* ID's info */
H5I_id_info_t * ret_value = NULL; /* Return value */
FUNC_ENTER_PACKAGE_NOERR
@@ -1469,15 +1602,53 @@ H5I__find_id(hid_t id)
/* Check for same ID as we have looked up last time */
if (type_info->last_id_info && type_info->last_id_info->id == id)
- ret_value = type_info->last_id_info;
+ id_info = type_info->last_id_info;
else {
/* Locate the ID node for the ID */
- ret_value = (H5I_id_info_t *)H5SL_search(type_info->ids, &id);
+ id_info = (H5I_id_info_t *)H5SL_search(type_info->ids, &id);
/* Remember this ID */
- type_info->last_id_info = ret_value;
+ type_info->last_id_info = id_info;
}
+ /* Check if this is a future ID */
+ H5_GCC_DIAG_OFF("cast-qual")
+ if (id_info && id_info->is_future) {
+ hid_t actual_id = H5I_INVALID_HID; /* ID for actual object */
+ void *future_object; /* Pointer to the future object */
+ void *actual_object; /* Pointer to the actual object */
+
+ /* Invoke the realize callback, to get the actual object */
+ if ((id_info->realize_cb)((void *)id_info->object, &actual_id) < 0)
+ HGOTO_DONE(NULL)
+
+ /* Verify that we received a valid ID, of the same type */
+ if (H5I_INVALID_HID == actual_id)
+ HGOTO_DONE(NULL)
+ if (H5I_TYPE(id) != H5I_TYPE(actual_id))
+ HGOTO_DONE(NULL)
+
+ /* Swap the actual object in for the future object */
+ future_object = (void *)id_info->object;
+ actual_object = H5I__remove_common(type_info, actual_id);
+ HDassert(actual_object);
+ id_info->object = actual_object;
+
+ /* Discard the future object */
+ if ((id_info->discard_cb)(future_object) < 0)
+ HGOTO_DONE(NULL)
+ future_object = NULL;
+
+ /* Change the ID from 'future' to 'actual' */
+ id_info->is_future = FALSE;
+ id_info->realize_cb = NULL;
+ id_info->discard_cb = NULL;
+ }
+ H5_GCC_DIAG_ON("cast-qual")
+
+ /* Set return value */
+ ret_value = id_info;
+
done:
FUNC_LEAVE_NOAPI(ret_value)
} /* end H5I__find_id() */