#include "H5SLmodule.h"
#include "H5private.h"
#include "H5Eprivate.h"
#include "H5FLprivate.h"
#include "H5MMprivate.h"
#include "H5SLprivate.h"
#define H5SL_LOCATE_SEARCH_FOUND(SLIST, X, I) \
{ \
HDassert(!X->removed); \
HGOTO_DONE(X->item); \
}
#define H5SL_LOCATE_SEARCH_DEFER_REMOVE_FOUND(SLIST, X, I) \
{ \
HDassert(!X->removed); \
X->removed = TRUE; \
HGOTO_DONE(X->item); \
}
#define H5SL_LOCATE_FIND_FOUND(SLIST, X, I) \
{ \
HDassert(!X->removed); \
HGOTO_DONE(X); \
}
#define H5SL_LOCATE_SCALAR_CMP(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
(*(TYPE *)((PNODE)->key) < *(TYPE *)PKEY)
#define H5SL_LOCATE_STRING_CMP(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
(((PNODE)->hashval == HASHVAL) ? \
(HDstrcmp((const char *)(PNODE)->key, (const char *)PKEY) < 0) : \
((PNODE)->hashval < HASHVAL))
#define H5SL_LOCATE_OBJ_CMP(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
((((TYPE *)((PNODE)->key))->fileno == ((TYPE *)PKEY)->fileno) \
? (((TYPE *)((PNODE)->key))->addr < ((TYPE *)PKEY)->addr) \
: (((TYPE *)((PNODE)->key))->fileno < ((TYPE *)PKEY)->fileno))
#define H5SL_LOCATE_GENERIC_CMP(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
((SLIST)->cmp((TYPE *)((PNODE)->key), (TYPE *)PKEY) < 0)
#define H5SL_LOCATE_SCALAR_EQ(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
(*(TYPE *)((PNODE)->key) == *(TYPE *)PKEY)
#define H5SL_LOCATE_STRING_EQ(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
(((PNODE)->hashval == HASHVAL) && (HDstrcmp((const char *)(PNODE)->key, (const char *)PKEY) == 0))
#define H5SL_LOCATE_OBJ_EQ(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
((((TYPE *)((PNODE)->key))->fileno == ((TYPE *)PKEY)->fileno) && (((TYPE *)((PNODE)->key))->addr == ((TYPE *)PKEY)->addr))
#define H5SL_LOCATE_GENERIC_EQ(SLIST, TYPE, PNODE, PKEY, HASHVAL) \
((SLIST)->cmp((TYPE *)((PNODE)->key), (TYPE *)PKEY) == 0)
#define H5SL_LOCATE_SCALAR_HASHINIT(KEY, HASHVAL)
#define H5SL_LOCATE_STRING_HASHINIT(KEY, HASHVAL) \
HASHVAL = H5_hash_string((const char *)KEY);
#define H5SL_LOCATE_OBJ_HASHINIT(KEY, HASHVAL)
#define H5SL_LOCATE_GENERIC_HASHINIT(KEY, HASHVAL)
#define H5SL_LOCATE_OPT(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
{ \
int _i; \
unsigned _count; \
\
H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \
_count = 0; \
while(_count < 3 && X->forward[_i] && \
H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL) ) { \
X = X->forward[_i]; \
_count++; \
} \
} \
X = X->forward[0]; \
if(X != NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(SLIST, TYPE, X, KEY, HASHVAL) ) { \
\
H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, _i) \
} \
}
#define H5SL_LOCATE_SAFE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
{ \
int _i; \
H5SL_node_t *_low = X; \
H5SL_node_t *_high = NULL; \
\
H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \
X = _low->forward[_i]; \
while(X != _high) { \
if(!X->removed) { \
if(H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, X, KEY, HASHVAL)) \
_low = X; \
else \
break; \
} \
X = X->forward[_i]; \
} \
_high = X; \
if(X != NULL && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(SLIST, TYPE, X, KEY, HASHVAL) ) { \
\
H5_GLUE3(H5SL_LOCATE_,OP,_FOUND)(SLIST, X, _i) \
break; \
} \
} \
}
#define H5SL_LOCATE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
{ \
if((SLIST)->safe_iterating) \
H5SL_LOCATE_SAFE(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
else \
H5SL_LOCATE_OPT(OP, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
}
#define H5SL_GROW(X, LVL, ERR) \
{ \
\
if(LVL + 1 >= 1u << X->log_nalloc) { \
H5SL_node_t **_tmp; \
HDassert(LVL + 1 == 1u << X->log_nalloc); \
\
X->log_nalloc++; \
\
\
if(X->log_nalloc >= H5SL_fac_nused_g) { \
HDassert(X->log_nalloc == H5SL_fac_nused_g); \
\
\
if(H5SL_fac_nused_g >= H5SL_fac_nalloc_g) { \
HDassert(H5SL_fac_nused_g == H5SL_fac_nalloc_g); \
\
H5SL_fac_nalloc_g *= 2; \
if(NULL == (H5SL_fac_g = (H5FL_fac_head_t **)H5MM_realloc( \
(void *)H5SL_fac_g, H5SL_fac_nalloc_g \
* sizeof(H5FL_fac_head_t *)))) \
HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, ERR, "memory allocation failed") \
} \
\
\
H5SL_fac_g[H5SL_fac_nused_g] = H5FL_fac_init((1u << H5SL_fac_nused_g) * sizeof(H5SL_node_t *)); \
H5SL_fac_nused_g++; \
} \
\
\
if(NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \
HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, ERR, "memory allocation failed") \
H5MM_memcpy((void *)_tmp, (const void *)X->forward, (LVL + 1) * sizeof(H5SL_node_t *)); \
X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc-1], (void *)X->forward); \
X->forward = _tmp; \
} \
\
X->level++; \
}
#define H5SL_SHRINK(X, LVL) \
{ \
\
if(LVL <= 1u << (X->log_nalloc - 1)) { \
H5SL_node_t **_tmp; \
HDassert(LVL == 1u << (X->log_nalloc - 1)); \
X->log_nalloc--; \
\
\
if(NULL == (_tmp = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[X->log_nalloc]))) \
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed") \
H5MM_memcpy((void *)_tmp, (const void *)X->forward, (LVL) * sizeof(H5SL_node_t *)); \
X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[X->log_nalloc+1], (void *)X->forward); \
X->forward = _tmp; \
} \
\
X->level--; \
}
#define H5SL_PROMOTE(SLIST, X, PREV, ERR) \
{ \
size_t _lvl = X->level; \
\
H5SL_GROW(X, _lvl, ERR); \
\
if(_lvl == (size_t) SLIST->curr_level) { \
HDassert(PREV == SLIST->header); \
\
H5SL_GROW(PREV, _lvl, ERR) \
SLIST->curr_level++; \
X->forward[_lvl+1] = NULL; \
} else { \
HDassert(_lvl < (size_t) SLIST->curr_level); \
X->forward[_lvl+1] = PREV->forward[_lvl+1]; \
} \
PREV->forward[_lvl+1] = X; \
}
#define H5SL_DEMOTE(X, PREV) \
{ \
size_t _lvl = X->level; \
\
HDassert(PREV->forward[_lvl] == X); \
PREV->forward[_lvl] = X->forward[_lvl]; \
H5SL_SHRINK(X, _lvl); \
}
#define H5SL_INSERT(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
{ \
H5SL_node_t *_last = X; \
H5SL_node_t *_next = NULL; \
H5SL_node_t *_drop; \
int _count; \
int _i; \
\
H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
for(_i = (int)SLIST->curr_level; _i >= 0; _i--) { \
\
\
_drop = NULL; \
for(_count = 0; ; _count++) { \
\
if(X->forward[_i] == _next) { \
if(!_drop) \
_drop = X; \
break; \
} \
\
\
if(!_drop && !H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL)) \
_drop = X; \
\
\
\
if(_count == 2) { \
if(!_drop) \
_drop = X->forward[_i]; \
_count = 3; \
break; \
} \
X = X->forward[_i]; \
} \
HDassert(!_drop->forward[_i] || \
!H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, _drop->forward[_i], KEY, HASHVAL)); \
\
\
if(_count == 3) { \
HDassert(X == _last->forward[_i]->forward[_i]); \
H5SL_PROMOTE(SLIST, X, _last, NULL) \
} \
\
\
X = _last = _drop; \
_next = _drop->forward[_i]; \
} \
\
if(_next && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(SLIST, TYPE, _next, KEY, HASHVAL)) \
HGOTO_ERROR(H5E_SLIST, H5E_CANTINSERT, NULL, "can't insert duplicate key") \
}
#define H5SL_REMOVE(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
{ \
\
if(SLIST->safe_iterating) \
H5SL_LOCATE(SEARCH_DEFER_REMOVE, CMP, SLIST, X, TYPE, KEY, HASHVAL) \
else { \
H5SL_node_t *_last = X; \
H5SL_node_t *_llast = X; \
H5SL_node_t *_next = NULL; \
H5SL_node_t *_drop = NULL; \
H5SL_node_t *_ldrop = NULL; \
H5SL_node_t *_head = SLIST->header; \
int _count; \
int _i = (int)SLIST->curr_level; \
\
if(_i < 0) \
HGOTO_DONE(NULL); \
\
H5_GLUE3(H5SL_LOCATE_,CMP,_HASHINIT)(KEY, HASHVAL) \
\
\
while(X && (!X->key || H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, X, KEY, HASHVAL))) { \
_llast = _last; \
_last = X; \
X = X->forward[_i]; \
} \
_next = X; \
\
\
for(_i--; _i >= 0; _i--) { \
\
\
\
\
X = _ldrop = _last; \
_drop = NULL; \
for(_count = 0; ; _count++) { \
\
if(X->forward[_i] == _next) { \
if(!_drop) \
_drop = X; \
break; \
} \
\
\
\
if(_drop) { \
HDassert(_count >= 1); \
_count = 2; \
break; \
} else { \
\
if (!H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, X->forward[_i], KEY, HASHVAL)) { \
_drop = X; \
\
if(_count) { \
_count = 2; \
break; \
} \
} \
else \
_ldrop = X; \
} \
\
\
\
if(_count == 2) { \
if(!_drop) \
_drop = X->forward[_i]; \
break; \
} \
X = X->forward[_i]; \
} \
HDassert(_count >= 1 && _count <= 3); \
HDassert(!_drop->forward[_i] || \
!H5_GLUE3(H5SL_LOCATE_,CMP,_CMP)(SLIST, TYPE, _drop->forward[_i], KEY, HASHVAL)); \
\
\
if(_count == 1) { \
\
if(_llast == _last) { \
\
\
\
\
_llast = _next->forward[_i+1]; \
\
\
H5SL_DEMOTE(_next, _last) \
\
\
if(_next->forward[_i]->forward[_i] != _llast) { \
X = _next->forward[_i]; \
H5SL_PROMOTE(SLIST, X, _last, NULL) \
} else if(!_head->forward[_i+1]) { \
\
HDassert(_i == SLIST->curr_level - 1); \
HDassert((size_t) SLIST->curr_level == _head->level); \
\
H5SL_SHRINK(_head, (size_t) (_i+1)) \
SLIST->curr_level--; \
} \
} else { \
\
\
\
\
X = _llast->forward[_i]; \
for(_count = 1; _count < 3 && X->forward[_i] != _last; _count++) \
X = X->forward[_i]; \
HDassert(X->forward[_i] == _last); \
\
\
H5SL_DEMOTE(_last, _llast) \
\
\
if(_count >= 2) \
H5SL_PROMOTE(SLIST, X, _llast, NULL) \
else if(!_head->forward[_i+1]) { \
\
HDassert(_i == SLIST->curr_level - 1); \
HDassert((size_t) SLIST->curr_level == _head->level); \
\
H5SL_SHRINK(_head, (size_t) (_i+1)) \
SLIST->curr_level--; \
} \
} \
} \
\
\
_llast = _ldrop; \
_last = _drop; \
_next = _drop->forward[_i]; \
} \
\
\
if(_next && H5_GLUE3(H5SL_LOCATE_,CMP,_EQ)(SLIST, TYPE, _next, KEY, HASHVAL)) { \
void *tmp = _next->item; \
X = _next; \
\
\
\
if(X->level) { \
X = X->backward; \
_next->key = X->key; \
_next->item = X->item; \
_next->hashval = X->hashval; \
} \
HDassert(!X->level); \
\
\
X->backward->forward[0] = X->forward[0]; \
if(SLIST->last == X) \
SLIST->last = X->backward; \
else \
X->forward[0]->backward = X->backward; \
SLIST->nobjs--; \
X->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[0], X->forward); \
X = H5FL_FREE(H5SL_node_t, X); \
\
HGOTO_DONE(tmp); \
} \
} \
}
#define H5SL_SEARCH(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
H5SL_LOCATE(SEARCH, CMP, SLIST, X, TYPE, KEY, HASHVAL)
#define H5SL_FIND(CMP, SLIST, X, TYPE, KEY, HASHVAL) \
H5SL_LOCATE(FIND, CMP, SLIST, X, TYPE, KEY, HASHVAL)
struct H5SL_node_t {
const void *key;
void *item;
size_t level;
size_t log_nalloc;
uint32_t hashval;
hbool_t removed;
struct H5SL_node_t **forward;
struct H5SL_node_t *backward;
};
struct H5SL_t {
H5SL_type_t type;
H5SL_cmp_t cmp;
int curr_level;
size_t nobjs;
H5SL_node_t *header;
H5SL_node_t *last;
hbool_t safe_iterating;
};
static H5SL_node_t * H5SL_new_node(void *item, const void *key, uint32_t hashval);
static H5SL_node_t *H5SL_insert_common(H5SL_t *slist, void *item, const void *key);
static herr_t H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data);
static herr_t H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data);
hbool_t H5_PKG_INIT_VAR = FALSE;
H5FL_DEFINE_STATIC(H5SL_t);
H5FL_DEFINE_STATIC(H5SL_node_t);
static H5FL_fac_head_t **H5SL_fac_g;
static size_t H5SL_fac_nused_g;
static size_t H5SL_fac_nalloc_g;
herr_t
H5SL__init_package(void)
{
FUNC_ENTER_PACKAGE_NOERR
H5SL_fac_g = (H5FL_fac_head_t **)H5MM_malloc(sizeof(H5FL_fac_head_t *));
HDassert(H5SL_fac_g);
H5SL_fac_nalloc_g = 1;
H5SL_fac_g[0] = H5FL_fac_init(sizeof(H5SL_node_t *));
HDassert(H5SL_fac_g[0]);
H5SL_fac_nused_g = 1;
FUNC_LEAVE_NOAPI(SUCCEED)
}
int H5SL_term_package(void)
{
int n = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
if(H5_PKG_INIT_VAR) {
if(H5SL_fac_nused_g > 0) {
size_t i;
herr_t H5_ATTR_NDEBUG_UNUSED ret;
for(i = 0; i < H5SL_fac_nused_g; i++) {
ret = H5FL_fac_term(H5SL_fac_g[i]);
HDassert(ret >= 0);
}
H5SL_fac_nused_g = 0;
n++;
}
if(H5SL_fac_g) {
H5SL_fac_g = (H5FL_fac_head_t **)H5MM_xfree((void *)H5SL_fac_g);
H5SL_fac_nalloc_g = 0;
n++;
}
if(0 == n)
H5_PKG_INIT_VAR = FALSE;
}
FUNC_LEAVE_NOAPI(n)
}
static H5SL_node_t *
H5SL_new_node(void *item, const void *key, uint32_t hashval)
{
H5SL_node_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
if(NULL == (ret_value = (H5SL_node_t *)H5FL_MALLOC(H5SL_node_t)))
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
ret_value->key = key;
ret_value->item = item;
ret_value->level = 0;
ret_value->hashval = hashval;
ret_value->removed = FALSE;
if(NULL == (ret_value->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0]))) {
ret_value = H5FL_FREE(H5SL_node_t, ret_value);
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
}
ret_value->log_nalloc = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static H5SL_node_t *
H5SL_insert_common(H5SL_t *slist, void *item, const void *key)
{
H5SL_node_t *x;
H5SL_node_t *prev;
uint32_t hashval = 0;
H5SL_node_t *ret_value;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
HDassert(key);
prev=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_INSERT(SCALAR, slist, prev, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_INSERT(SCALAR, slist, prev, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_INSERT(STRING, slist, prev, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_INSERT(SCALAR, slist, prev, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_INSERT(SCALAR, slist, prev, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_INSERT(SCALAR, slist, prev, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_INSERT(OBJ, slist, prev, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_INSERT(SCALAR, slist, prev, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_INSERT(GENERIC, slist, prev, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
if(slist->curr_level < 0)
slist->curr_level = 0;
if(NULL == (x = H5SL_new_node(item, key, hashval)))
HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node")
x->backward = prev;
x->forward[0] = prev->forward[0];
prev->forward[0] = x;
if(x->forward[0])
x->forward[0]->backward = x;
else {
HDassert(slist->last == prev);
slist->last = x;
}
slist->nobjs++;
ret_value=x;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SL_release_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
H5SL_node_t *node, *next_node;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
node = slist->header->forward[0];
while(node) {
next_node = node->forward[0];
if(op)
(void)(op)(node->item, (void *)node->key, op_data);
node->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], node->forward);
node = H5FL_FREE(H5SL_node_t, node);
node = next_node;
}
slist->header->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[slist->header->log_nalloc], slist->header->forward);
if(NULL == (slist->header->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0])))
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, FAIL, "memory allocation failed")
slist->header->forward[0] = NULL;
slist->header->log_nalloc = 0;
slist->header->level = 0;
slist->last = slist->header;
slist->curr_level = -1;
slist->nobjs = 0;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
static herr_t
H5SL_close_common(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
if(H5SL_release_common(slist, op, op_data) < 0)
HGOTO_ERROR(H5E_SLIST, H5E_CANTFREE, FAIL, "can't release skip list nodes")
slist->header->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[slist->header->log_nalloc], slist->header->forward);
slist->header = H5FL_FREE(H5SL_node_t, slist->header);
slist = H5FL_FREE(H5SL_t, slist);
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5SL_t *
H5SL_create(H5SL_type_t type, H5SL_cmp_t cmp)
{
H5SL_t *new_slist = NULL;
H5SL_node_t *header;
H5SL_t *ret_value = NULL;
FUNC_ENTER_NOAPI(NULL)
HDassert(type >= H5SL_TYPE_INT && type <= H5SL_TYPE_GENERIC);
if(NULL == (new_slist = H5FL_MALLOC(H5SL_t)))
HGOTO_ERROR(H5E_SLIST, H5E_NOSPACE, NULL, "memory allocation failed")
new_slist->type = type;
HDassert((type == H5SL_TYPE_GENERIC) == !!cmp);
new_slist->cmp = cmp;
new_slist->curr_level = -1;
new_slist->nobjs = 0;
new_slist->safe_iterating = FALSE;
if(NULL == (header = H5SL_new_node(NULL, NULL, (uint32_t)ULONG_MAX)))
HGOTO_ERROR(H5E_SLIST ,H5E_NOSPACE, NULL, "can't create new skip list node")
header->forward[0] = NULL;
header->backward = NULL;
new_slist->header = header;
new_slist->last = header;
ret_value = new_slist;
done:
if(ret_value == NULL) {
if(new_slist != NULL)
new_slist = H5FL_FREE(H5SL_t, new_slist);
}
FUNC_LEAVE_NOAPI(ret_value)
}
size_t
H5SL_count(H5SL_t *slist)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(!slist->safe_iterating);
FUNC_LEAVE_NOAPI(slist->nobjs)
}
herr_t
H5SL_insert(H5SL_t *slist, void *item, const void *key)
{
herr_t ret_value=SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
HDassert(key);
HDassert(!slist->safe_iterating);
if(H5SL_insert_common(slist,item,key)==NULL)
HGOTO_ERROR(H5E_SLIST,H5E_CANTINSERT,FAIL,"can't create new skip list node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5SL_node_t *
H5SL_add(H5SL_t *slist, void *item, const void *key)
{
H5SL_node_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
HDassert(key);
HDassert(!slist->safe_iterating);
if((ret_value=H5SL_insert_common(slist,item,key))==NULL)
HGOTO_ERROR(H5E_SLIST,H5E_CANTINSERT,NULL,"can't create new skip list node")
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5SL_remove(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
HDassert(key);
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_REMOVE(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_REMOVE(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_REMOVE(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_REMOVE(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_REMOVE(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_REMOVE(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_REMOVE(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_REMOVE(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_REMOVE(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5SL_remove_first(H5SL_t *slist)
{
void *ret_value = NULL;
H5SL_node_t *head = slist->header;
H5SL_node_t *tmp = slist->header->forward[0];
H5SL_node_t *next;
size_t level;
size_t i;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
HDassert(!slist->safe_iterating);
H5_CHECK_OVERFLOW(slist->curr_level, int, size_t);
level = (size_t)slist->curr_level;
if(slist->last != slist->header) {
ret_value = tmp->item;
HDassert(level == head->level);
HDassert(0 == tmp->level);
head->forward[0] = tmp->forward[0];
if(slist->last == tmp)
slist->last = head;
else
tmp->forward[0]->backward = head;
slist->nobjs--;
tmp->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[0], tmp->forward);
tmp = H5FL_FREE(H5SL_node_t, tmp);
for(i=0; i < level; i++) {
next = head->forward[i+1];
HDassert(next);
if(head->forward[i] == next) {
tmp = next;
next = next->forward[i+1];
HDassert(tmp->level == i+1);
H5SL_DEMOTE(tmp, head)
if(tmp->forward[i]->forward[i] != next) {
HDassert(tmp->forward[i]->forward[i]->forward[i] == next ||
tmp->forward[i]->forward[i]->forward[i]->forward[i] == next);
tmp = tmp->forward[i];
H5SL_PROMOTE(slist, tmp, head, NULL);
break;
} else if(!head->forward[i+1]) {
HDassert(i == level - 1);
H5SL_SHRINK(head, level)
slist->curr_level--;
}
} else
break;
}
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5SL_search(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
void *ret_value;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(key);
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_SEARCH(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_SEARCH(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_SEARCH(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_SEARCH(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_SEARCH(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_SEARCH(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_SEARCH(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_SEARCH(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
ret_value=NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5SL_less(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(key);
HDassert(!slist->safe_iterating);
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_SEARCH(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_SEARCH(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_SEARCH(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_SEARCH(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_SEARCH(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_SEARCH(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_SEARCH(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_SEARCH(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
if(x==NULL) {
if(slist->last!=slist->header)
ret_value=slist->last->item;
else
ret_value=NULL;
}
else {
if(x->backward!=slist->header)
ret_value=x->backward->item;
else
ret_value=NULL;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
void *
H5SL_greater(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
void *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(key);
HDassert(!slist->safe_iterating);
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_SEARCH(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_SEARCH(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_SEARCH(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_SEARCH(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_SEARCH(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_SEARCH(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_SEARCH(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_SEARCH(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_SEARCH(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
if(x)
ret_value = x->item;
else
ret_value = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5SL_node_t *
H5SL_find(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
H5SL_node_t *ret_value;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(key);
x=slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_FIND(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_FIND(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_FIND(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_FIND(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_FIND(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_FIND(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_FIND(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_FIND(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
ret_value=NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5SL_node_t *
H5SL_below(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
H5SL_node_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(key);
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_FIND(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_FIND(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_FIND(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_FIND(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_FIND(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_FIND(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_FIND(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_FIND(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
if(NULL == x) {
if(slist->last != slist->header)
ret_value = slist->last;
else
ret_value = NULL;
}
else {
if(x->backward != slist->header)
ret_value = x->backward;
else
ret_value = NULL;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5SL_node_t *
H5SL_above(H5SL_t *slist, const void *key)
{
H5SL_node_t *x;
uint32_t hashval = 0;
H5SL_node_t *ret_value = NULL;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(key);
x = slist->header;
switch(slist->type) {
case H5SL_TYPE_INT:
H5SL_FIND(SCALAR, slist, x, const int, key, -)
break;
case H5SL_TYPE_HADDR:
H5SL_FIND(SCALAR, slist, x, const haddr_t, key, -)
break;
case H5SL_TYPE_STR:
H5SL_FIND(STRING, slist, x, char *, key, hashval)
break;
case H5SL_TYPE_HSIZE:
H5SL_FIND(SCALAR, slist, x, const hsize_t, key, -)
break;
case H5SL_TYPE_UNSIGNED:
H5SL_FIND(SCALAR, slist, x, const unsigned, key, -)
break;
case H5SL_TYPE_SIZE:
H5SL_FIND(SCALAR, slist, x, const size_t, key, -)
break;
case H5SL_TYPE_OBJ:
H5SL_FIND(OBJ, slist, x, const H5_obj_t, key, -)
break;
case H5SL_TYPE_HID:
H5SL_FIND(SCALAR, slist, x, const hid_t, key, -)
break;
case H5SL_TYPE_GENERIC:
H5SL_FIND(GENERIC, slist, x, const void, key, -)
break;
default:
HDassert(0 && "Unknown skiplist type!");
}
if(x)
ret_value = x;
else
ret_value = NULL;
done:
FUNC_LEAVE_NOAPI(ret_value)
}
H5SL_node_t *
H5SL_first(H5SL_t *slist)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(!slist->safe_iterating);
FUNC_LEAVE_NOAPI(slist->header->forward[0])
}
H5SL_node_t *
H5SL_next(H5SL_node_t *slist_node)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist_node);
HDassert(!slist_node->removed);
FUNC_LEAVE_NOAPI(slist_node->forward[0])
}
H5SL_node_t *
H5SL_prev(H5SL_node_t *slist_node)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist_node);
HDassert(!slist_node->removed);
FUNC_LEAVE_NOAPI(slist_node->backward->key==NULL ? NULL : slist_node->backward)
}
H5SL_node_t *
H5SL_last(H5SL_t *slist)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(!slist->safe_iterating);
FUNC_LEAVE_NOAPI(slist->last==slist->header ? NULL : slist->last)
}
void *
H5SL_item(H5SL_node_t *slist_node)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist_node);
HDassert(!slist_node->removed);
FUNC_LEAVE_NOAPI(slist_node->item)
}
herr_t
H5SL_iterate(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
H5SL_node_t *node;
H5SL_node_t *next;
herr_t ret_value = 0;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
node = slist->header->forward[0];
while(node != NULL) {
next = node->forward[0];
if(!node->removed)
if((ret_value = (op)(node->item, (void *)node->key, op_data)) != 0)
break;
node = next;
}
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5SL_release(H5SL_t *slist)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(!slist->safe_iterating);
H5SL_release_common(slist,NULL,NULL);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5SL_free(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
HDassert(!slist->safe_iterating);
H5SL_release_common(slist,op,op_data);
FUNC_LEAVE_NOAPI(SUCCEED)
}
herr_t
H5SL_try_free_safe(H5SL_t *slist, H5SL_try_free_op_t op, void *op_data)
{
H5SL_node_t *node, *next_node, *last_node;
htri_t op_ret;
herr_t ret_value = SUCCEED;
FUNC_ENTER_NOAPI_NOINIT
HDassert(slist);
HDassert(op);
HDassert(!slist->safe_iterating);
slist->safe_iterating = TRUE;
node = slist->header->forward[0];
while(node) {
if(!node->removed) {
if((op_ret = (op)(node->item , (void *)node->key, op_data)) < 0)
HGOTO_ERROR(H5E_SLIST, H5E_CALLBACK, FAIL, "callback operation failed")
if(op_ret)
node->removed = TRUE;
}
node = node->forward[0];
}
slist->safe_iterating = FALSE;
node = slist->header->forward[0];
last_node = slist->header;
while(node) {
next_node = node->forward[0];
if(node->removed) {
node->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], node->forward);
node = H5FL_FREE(H5SL_node_t, node);
slist->nobjs--;
}
else {
if(node->level > 0) {
node->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[node->log_nalloc], (void *)node->forward);
if(NULL == (node->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0])))
HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, FAIL, "memory allocation failed")
node->log_nalloc = 0;
node->level = 0;
}
last_node->forward[0] = node;
node->backward = last_node;
last_node = node;
}
node = next_node;
}
last_node->forward[0] = NULL;
slist->last = last_node;
if(slist->curr_level > 0) {
HDassert(slist->header->level == (size_t)slist->curr_level);
node = slist->header->forward[0];
slist->header->forward = (H5SL_node_t **)H5FL_FAC_FREE(H5SL_fac_g[slist->header->log_nalloc], (void *)slist->header->forward);
if(NULL == (slist->header->forward = (H5SL_node_t **)H5FL_FAC_MALLOC(H5SL_fac_g[0])))
HGOTO_ERROR(H5E_SLIST, H5E_CANTALLOC, FAIL, "memory allocation failed")
slist->header->forward[0] = node;
slist->header->log_nalloc = 0;
slist->header->level = 0;
}
if(slist->nobjs > 0) {
int i;
HDassert(slist->header->forward[0]);
slist->curr_level = 0;
for(i = 0; slist->curr_level >= i; i++) {
HDassert(slist->curr_level == i);
node = last_node = slist->header;
while(1) {
HDassert(node->forward[i]);
node = node->forward[i]->forward[i];
if(!node)
break;
node = node->forward[i];
if(!node || !node->forward[i])
break;
H5SL_PROMOTE(slist, node, last_node, FAIL)
last_node = node;
}
}
}
else {
HDassert(!slist->header->forward[0]);
HDassert(slist->last == slist->header);
HDassert(slist->nobjs == 0);
slist->curr_level = -1;
}
done:
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5SL_destroy(H5SL_t *slist, H5SL_operator_t op, void *op_data)
{
herr_t ret_value=SUCCEED;
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
(void)H5SL_close_common(slist,op,op_data);
FUNC_LEAVE_NOAPI(ret_value)
}
herr_t
H5SL_close(H5SL_t *slist)
{
FUNC_ENTER_NOAPI_NOINIT_NOERR
HDassert(slist);
(void)H5SL_close_common(slist,NULL,NULL);
FUNC_LEAVE_NOAPI(SUCCEED)
}