} treeroots;
long count;
ul_hashtab_hashval_t hashmask;
+ unsigned char sizestep;
} ul_hashtab_cust_table_field_t;
typedef int (ul_hashtab_resize_insert_fnc_t)(ul_hashtab_cust_table_field_t *table_field, gavl_node_t *treenode) UL_ATTR_REENTRANT;
+typedef struct ul_hashtab_sizestep {
+ ul_hashtab_hashval_t toshrink;
+ ul_hashtab_hashval_t toexpand;
+ ul_hashtab_hashval_t size;
+} ul_hashtab_sizestep_t;
+
+static inline int ul_hashtab_sizestep_max(const ul_hashtab_sizestep_t *steptab)
+{
+ return steptab[0].toshrink;
+}
+
+const ul_hashtab_sizestep_t *ul_hashtab_sizestep_global;
+const ul_hashtab_sizestep_t * const ul_hashtab_sizestep_default;
+
+#define ul_hashtab_sizestep_null ((ul_hashtab_sizestep_t *)0)
+
void ul_hashtab_init_table_field_primitive(ul_hashtab_cust_table_field_t *table_field);
int ul_hashtab_delete_all_primitive(ul_hashtab_cust_table_field_t *table_field);
int ul_hashtab_resize_primitive(ul_hashtab_cust_table_field_t *table_field,
UL_HASTAB_CUST_NODE_INT_IMP(cust3, cust3_table_t, cust3_item_t, cust3_key_t,
my_table, my_node, my_val, cust3_cmp_fnc, cust3_hash_fnc,
- cust3_hash_get_fnc, cust_hash_prep_fnc, 0, 0)
+ cust3_hash_get_fnc, cust_hash_prep_fnc, ul_hashtab_sizestep_global)
cust3_table_t cust3_table;
}
if(argc>=3) {
tablepow=atol(argv[2]);
+ ul_hashtab_sizestep_global=ul_hashtab_sizestep_null;
}
cust3_resize_table(table, 1<<tablepow);
#define UL_HASTAB_CUST_NODE_INT_IMP(cust_prefix, cust_table_t, cust_item_t, cust_key_t,\
cust_table_field, cust_item_node, cust_item_key, cust_cmp_fnc, cust_hash_fnc, \
- cust_hash_get_fnc, cust_hash_prep_fnc, cust_expand_ratio, cust_shrink_ratio) \
+ cust_hash_get_fnc, cust_hash_prep_fnc, cust_sizestep) \
GAVL_CUST_NODE_INT_DEC_SCOPE(static, cust_prefix##_privtree, ul_hashtab_treeroot_t, cust_item_t, cust_key_t,\
treeroot, cust_item_node.treenode, cust_item_key, cust_cmp_fnc) \
GAVL_CUST_NODE_INT_IMP(cust_prefix##_privtree, ul_hashtab_treeroot_t, cust_item_t, cust_key_t,\
&(table->cust_table_field.treeroots.treetable[cust_hash_fnc(key)&table->cust_table_field.hashmask]);\
} \
\
+static inline \
+void cust_prefix##_privdummy(cust_table_t *table) \
+{/*used to suppress warning about unused static function generated by GAVL*/\
+ cust3_privtree_init_root_field(&(table->cust_table_field.treeroots.treesingle));\
+} \
+\
static \
int cust_prefix##_privinternal_insert(cust_table_t *table, cust_item_t *item)\
{\
int cust_prefix##_insert(cust_table_t *table, cust_item_t *item)\
{\
int res;\
- if(cust_expand_ratio<=0?0:(table->cust_table_field.count/cust_expand_ratio>table->cust_table_field.hashmask)) \
- cust_prefix##_resize_table(table, (table->cust_table_field.hashmask+1)<<1);\
+ if((cust_sizestep)!=ul_hashtab_sizestep_null) \
+ if((table->cust_table_field.sizestep<ul_hashtab_sizestep_max(cust_sizestep))&& \
+ (table->cust_table_field.count>=(cust_sizestep)[table->cust_table_field.sizestep].toexpand)) {\
+ table->cust_table_field.sizestep++; \
+ cust_prefix##_resize_table(table, (cust_sizestep)[table->cust_table_field.sizestep].size);\
+ } \
cust_hash_prep_fnc(item);\
res=cust_prefix##_privinternal_insert(table, item);\
if(res>0) \
res=cust_prefix##_privtree_delete(cust_prefix##_privtree_tree4item(table, item), item);\
if(res>0) { \
table->cust_table_field.count--; \
- if(cust_shrink_ratio<=0?0:(table->cust_table_field.count/cust_shrink_ratio<table->cust_table_field.hashmask)) \
- cust_prefix##_resize_table(table, (table->cust_table_field.hashmask>>1)+1);\
+ if(((cust_sizestep)!=ul_hashtab_sizestep_null)&&table->cust_table_field.sizestep) \
+ if(table->cust_table_field.sizestep>ul_hashtab_sizestep_max(cust_sizestep)) \
+ table->cust_table_field.sizestep=ul_hashtab_sizestep_max(cust_sizestep); \
+ if(table->cust_table_field.count<=(cust_sizestep)[table->cust_table_field.sizestep].toshrink) {\
+ table->cust_table_field.sizestep--; \
+ cust_prefix##_resize_table(table, (cust_sizestep)[table->cust_table_field.sizestep].size);\
+ } \
}\
return res; \
} \
if(cust_prefix##_privtree_search_node(treeroot, key, &node)) \
return NULL; \
cust_prefix##_privtree_delete_node((ul_hashtab_treeroot_t *)treeroot, node); \
+ table->cust_table_field.count--; \
return cust_prefix##_privtree_node2item(NULL,node); \
} \
\
{
if(table_field->hashmask)
free(table_field->treeroots.treetable);
+ table_field->sizestep=0;
table_field->hashmask=0;
table_field->count=0;
table_field->treeroots.treesingle.treeroot=NULL;
(*pptreeroot)++;
} while (1);
}
+
+#undef TABENT
+#define TABENT(pow) ((ul_hashtab_hashval_t)(1l<<(pow)))
+
+static const ul_hashtab_sizestep_t ul_hashtab_sizestep_default_table[]={
+ { ((ul_hashtab_hashval_t)~0l)<(1l<<8)?2:
+ ((ul_hashtab_hashval_t)~0l)<(1l<<16)?5:8,
+ TABENT( 1), TABENT( 0)},
+ {TABENT( 0), TABENT( 4), TABENT( 4)},
+ {TABENT( 3), TABENT( 6), TABENT( 6)},
+ {TABENT( 5), TABENT( 8), TABENT( 8)},
+ {TABENT( 7), TABENT(11), TABENT(10)},
+ {TABENT(10), TABENT(14), TABENT(12)},
+ {TABENT(13), TABENT(18), TABENT(14)},
+ {TABENT(17), TABENT(21), TABENT(16)},
+ {TABENT(16), 0, TABENT(18)},
+};
+
+const ul_hashtab_sizestep_t * const ul_hashtab_sizestep_default=ul_hashtab_sizestep_default_table;
+const ul_hashtab_sizestep_t *ul_hashtab_sizestep_global=ul_hashtab_sizestep_default_table;