simd_map remove
This commit is contained in:
parent
ab3e80f020
commit
cd30b70457
10
main.cpp
10
main.cpp
@ -186,6 +186,16 @@ void test_simd_map_basics() {
|
||||
assert(*simd_map_find(&smap, i) == (uint32_t)(cnt - i));
|
||||
}
|
||||
|
||||
/* Test removal */
|
||||
assert(simd_map_remove(&smap, 41) != 0);
|
||||
assert(simd_map_remove(&smap, 43) != 0);
|
||||
assert(simd_map_find(&smap, 41) == NULL);
|
||||
assert(simd_map_find(&smap, 43) == NULL);
|
||||
assert(simd_map_find(&smap, 42) != NULL);
|
||||
assert(simd_map_find(&smap, 99) != NULL);
|
||||
assert(simd_map_find(&smap, 98) != NULL);
|
||||
assert(simd_map_size(&smap) == 98);
|
||||
|
||||
/* Filled free */
|
||||
simd_map_free(&smap);
|
||||
}
|
||||
|
67
simd_map.h
67
simd_map.h
@ -109,6 +109,8 @@ non_simd_modulo:
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: Implement find_all(..) and delegate to it in find(..)
|
||||
|
||||
/** Returns if this key is stored in the map or not - returns NULL if does not exists. */
|
||||
static inline uint32_t *simd_map_find(simd_map *map, uint32_t key) {
|
||||
/* Do not process last element because of last incomplete lane */
|
||||
@ -131,7 +133,7 @@ static inline uint32_t *simd_map_find(simd_map *map, uint32_t key) {
|
||||
}
|
||||
|
||||
/** Useful if you know the key have never been before added (faster)! Returns 0 on errors, otherwise 1. */
|
||||
static inline char simd_map_force_insert(simd_map *map, uint32_t key, uint32_t value) {
|
||||
static inline SM_ALWAYS_INLINE char simd_map_force_insert(simd_map *map, uint32_t key, uint32_t value) {
|
||||
/* Handle storage growth needs. */
|
||||
uint32_t storage_needed = (map->lane_modulo == 0) ? 1 : 0;
|
||||
if(SM_UNLIKELY(map->end - map->usage_end < storage_needed)) {
|
||||
@ -163,7 +165,9 @@ static inline char simd_map_force_insert(simd_map *map, uint32_t key, uint32_t v
|
||||
return 1;
|
||||
}
|
||||
|
||||
/** Returns 0 on errors, otherwise 1 when added as new, 2 when already found got overwritten */
|
||||
/**
|
||||
* Returns 0 on errors, otherwise 1 when added as new, 2 when already found got overwritten
|
||||
*/
|
||||
static inline char simd_map_set(simd_map *map, uint32_t key, uint32_t value) {
|
||||
uint32_t *found = simd_map_find(map, key);
|
||||
if(!found) {
|
||||
@ -176,21 +180,74 @@ static inline char simd_map_set(simd_map *map, uint32_t key, uint32_t value) {
|
||||
}
|
||||
|
||||
/** Empties the map - this does not free resources, just makes it reusable! */
|
||||
static inline void simd_map_erase(simd_map *map) {
|
||||
static inline SM_ALWAYS_INLINE void simd_map_erase(simd_map *map) {
|
||||
map->usage_end = 0;
|
||||
map->lane_modulo = 0;
|
||||
}
|
||||
|
||||
/** Returns count of elements in the given simd_map */
|
||||
static inline size_t simd_map_size(simd_map *map) {
|
||||
static inline SM_ALWAYS_INLINE size_t simd_map_size(simd_map *map) {
|
||||
return (map->usage_end > 0) ?
|
||||
(((size_t)(map->usage_end) - 1) * 8 + map->lane_modulo) :
|
||||
0;
|
||||
}
|
||||
|
||||
/** Returns TRUE when map is empty and false otherwise - faster than simd_map_size(..) */
|
||||
static inline SM_ALWAYS_INLINE char simd_map_is_empty(simd_map *map) {
|
||||
return (map->usage_end == 0);
|
||||
}
|
||||
|
||||
/** Returns the key location for a given value location */
|
||||
static inline SM_ALWAYS_INLINE uint32_t *simd_map_key_location(uint32_t *value_location) {
|
||||
return value_location -= SM_LANE_SPAN;
|
||||
}
|
||||
|
||||
/** Returns the lastly inserted value's location in the map - you must ensure the map has elements! */
|
||||
static inline SM_ALWAYS_INLINE uint32_t *simd_map_last_location(simd_map *map) {
|
||||
return (map->lane_modulo > 0) ?
|
||||
&(map->lanes[map->usage_end - 1].values[map->lane_modulo - 1]) :
|
||||
&(map->lanes[map->usage_end - 1].values[SM_LANE_SPAN - 1]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the found location from the map.
|
||||
*
|
||||
* Most users should prefer simd_map_remove instead. This is an unchecked operation!
|
||||
*
|
||||
* This must be called right after a find(..) or find_all(..) operation,
|
||||
* because the pointer can get invalidated (for example by erase or remove).
|
||||
*
|
||||
* @param map The map to remove from
|
||||
* @param value_location The location returned by find(..) or find_all(..) and is not yet invalidated
|
||||
*/
|
||||
static inline SM_ALWAYS_INLINE void simd_map_remove_ptr(simd_map *map, uint32_t *value_location) {
|
||||
/* Overwrite with the last key-value */
|
||||
uint32_t *key_location = simd_map_key_location(value_location);
|
||||
uint32_t *last_value_location = simd_map_last_location(map);
|
||||
uint32_t *last_key_location = simd_map_key_location(last_value_location);
|
||||
*value_location = *last_value_location;
|
||||
*key_location = *last_key_location;
|
||||
|
||||
/* Shrink the data structure */
|
||||
if(map->lane_modulo > 0) {
|
||||
--(map->lane_modulo);
|
||||
} else {
|
||||
map->lane_modulo = SM_LANE_SPAN - 1;
|
||||
}
|
||||
}
|
||||
|
||||
/** Remove the given key from the map so its not stored anymore. Returns 1 when found and removed, 0 otherwise. */
|
||||
static inline int simd_map_remove(simd_map *map, uint32_t key) {
|
||||
assert(0); // TODO: Implement by swapping to end + shrink!
|
||||
if(SM_UNLIKELY(map->usage_end == 0)) return 0;
|
||||
|
||||
uint32_t *found = simd_map_find(map, key);
|
||||
if(found) {
|
||||
simd_map_remove_ptr(map, found);
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user