fixed not needing double loops but fixing bug of not first finding results

This commit is contained in:
Richard Thier 2024-10-21 13:27:04 +02:00
parent cdd9c77892
commit a26b411fd4
2 changed files with 47 additions and 33 deletions

View File

@ -105,6 +105,22 @@ void test_basics(amap mapdo, void *map) {
assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "meaningless1", NULL)));
assert(*iptr == 42);
assert(iptr == &i);
/* Check the case where we have same 8-long prefix for multiple and they should be different */
int long_1 = 1;
int long_2 = 2;
int long_3 = 3;
assert(NULL != mapdo(map, AMAP_SET, "very_long_test_key_1", &long_1));
assert(NULL != mapdo(map, AMAP_SET, "very_long_test_key_2", &long_2));
assert(NULL != mapdo(map, AMAP_SET, "very_long_test_key_3", &long_3));
assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "very_long_test_key_1", NULL)));
assert(*iptr == 1);
assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "very_long_test_key_2", NULL)));
assert(*iptr == 2);
assert(NULL != (iptr = (int *)mapdo(map, AMAP_GET, "very_long_test_key_3", NULL)));
assert(*iptr == 3);
}
int main() {

64
simap.h
View File

@ -128,46 +128,44 @@ static inline simap_ptr64 *simap_search_internal(simap_instance *map, const char
/* Lookup prefix (fast-key) - hopefully this gets vectorized (should be)!!! */
auint64 *base = (auint64 *) (map->base);
auint64 *end = (auint64 *)((uint8_t *)base + (map->usage_end));
auint64 *tipp = NULL;
auint64 *nutipp = make_tipp(base, prefix.u64, end);
while(tipp != nutipp) {
tipp = nutipp;
while(tipp < end) {
/* Fast lookup, because found prefix */
assert((*tipp == prefix.u64));
auint64 *tipp = make_tipp(base, prefix.u64, end);
while(tipp < end) {
/* First check the remains of the string (only if needed) */
if(!is_smallkey) {
char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t));
if(strcmp(keyremains, tippremains) != 0) {
continue;
}
}
/* Need detailed lookup, because found the prefix */
assert((*tipp == prefix.u64));
simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2));
/* Check back & forth (jump validation) */
uint32_t previ = *((uint32_t *)(tipp - 1));
if(previ == (uint32_t) -1) {
/* Expect it be good if it was first insert ever? Statistically rare to be not like it */
return ptr;
}
uint32_t prevnexi = *(uint32_t *)(((uint8_t *)base) + previ
+ sizeof(simap_ptr64)
+ sizeof(uint32_t));
auint64 *retipp = (auint64 *)(((uint8_t *)base + prevnexi)
+ sizeof(simap_ptr64) + sizeof(uint32_t) +
+ sizeof(uint32_t));
if(retipp != tipp) {
/* First check the remains of the string (only if needed) */
if(!is_smallkey) {
char *tippremains = (char *)((uint8_t *)tipp + sizeof(uint64_t));
if(strcmp(keyremains, tippremains) != 0) {
tipp = make_tipp(tipp + 1, prefix.u64, end);
continue;
}
}
/* Can have the (statistically checked) pointer */
simap_ptr64 *ptr = (simap_ptr64 *)((uint8_t *) (tipp - 2));
/* Check back & forth (jump validation) */
uint32_t previ = *((uint32_t *)(tipp - 1));
if(previ == (uint32_t) -1) {
/* Expect it be good if it was first insert ever? Statistically rare to be not like it */
return ptr;
}
nutipp = make_tipp((auint64 *) base, prefix.u64, end);
uint32_t prevnexi = *(uint32_t *)(((uint8_t *)base) + previ
+ sizeof(simap_ptr64)
+ sizeof(uint32_t));
auint64 *retipp = (auint64 *)(((uint8_t *)base + prevnexi)
+ sizeof(simap_ptr64) + sizeof(uint32_t) +
+ sizeof(uint32_t));
if(retipp != tipp) {
tipp = make_tipp(tipp + 1, prefix.u64, end);
continue;
}
/* Can have the (statistically checked) pointer */
return ptr;
}
/* Haven't found anything */