mirror of
https://github.com/Ed94/Odin.git
synced 2026-08-06 07:38:48 +00:00
Add PtrMap, begin working change Map to PtrMap where possible
This commit is contained in:
+6
-9
@@ -1135,8 +1135,7 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) {
|
|||||||
mutex_lock(&info->type_info_mutex);
|
mutex_lock(&info->type_info_mutex);
|
||||||
|
|
||||||
isize entry_index = -1;
|
isize entry_index = -1;
|
||||||
HashKey key = hash_type(type);
|
isize *found_entry_index = map_get(&info->type_info_map, type);
|
||||||
isize *found_entry_index = map_get(&info->type_info_map, key);
|
|
||||||
if (found_entry_index) {
|
if (found_entry_index) {
|
||||||
entry_index = *found_entry_index;
|
entry_index = *found_entry_index;
|
||||||
}
|
}
|
||||||
@@ -1145,11 +1144,10 @@ isize type_info_index(CheckerInfo *info, Type *type, bool error_on_failure) {
|
|||||||
// TODO(bill): This is O(n) and can be very slow
|
// TODO(bill): This is O(n) and can be very slow
|
||||||
for_array(i, info->type_info_map.entries){
|
for_array(i, info->type_info_map.entries){
|
||||||
auto *e = &info->type_info_map.entries[i];
|
auto *e = &info->type_info_map.entries[i];
|
||||||
Type *prev_type = cast(Type *)cast(uintptr)e->key.key;
|
if (are_types_identical(e->key, type)) {
|
||||||
if (are_types_identical(prev_type, type)) {
|
|
||||||
entry_index = e->value;
|
entry_index = e->value;
|
||||||
// NOTE(bill): Add it to the search map
|
// NOTE(bill): Add it to the search map
|
||||||
map_set(&info->type_info_map, key, entry_index);
|
map_set(&info->type_info_map, type, entry_index);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1484,7 +1482,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
|
|||||||
|
|
||||||
add_type_info_dependency(c->decl, t);
|
add_type_info_dependency(c->decl, t);
|
||||||
|
|
||||||
auto found = map_get(&c->info->type_info_map, hash_type(t));
|
auto found = map_get(&c->info->type_info_map, t);
|
||||||
if (found != nullptr) {
|
if (found != nullptr) {
|
||||||
// Types have already been added
|
// Types have already been added
|
||||||
return;
|
return;
|
||||||
@@ -1494,8 +1492,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
|
|||||||
isize ti_index = -1;
|
isize ti_index = -1;
|
||||||
for_array(i, c->info->type_info_map.entries) {
|
for_array(i, c->info->type_info_map.entries) {
|
||||||
auto *e = &c->info->type_info_map.entries[i];
|
auto *e = &c->info->type_info_map.entries[i];
|
||||||
Type *prev_type = cast(Type *)cast(uintptr)e->key.key;
|
if (are_types_identical(t, e->key)) {
|
||||||
if (are_types_identical(t, prev_type)) {
|
|
||||||
// Duplicate entry
|
// Duplicate entry
|
||||||
ti_index = e->value;
|
ti_index = e->value;
|
||||||
prev = true;
|
prev = true;
|
||||||
@@ -1508,7 +1505,7 @@ void add_type_info_type_internal(CheckerContext *c, Type *t) {
|
|||||||
ti_index = c->info->type_info_types.count;
|
ti_index = c->info->type_info_types.count;
|
||||||
array_add(&c->info->type_info_types, t);
|
array_add(&c->info->type_info_types, t);
|
||||||
}
|
}
|
||||||
map_set(&c->checker->info.type_info_map, hash_type(t), ti_index);
|
map_set(&c->checker->info.type_info_map, t, ti_index);
|
||||||
|
|
||||||
if (prev) {
|
if (prev) {
|
||||||
// NOTE(bill): If a previous one exists already, no need to continue
|
// NOTE(bill): If a previous one exists already, no need to continue
|
||||||
|
|||||||
+1
-1
@@ -321,7 +321,7 @@ struct CheckerInfo {
|
|||||||
|
|
||||||
BlockingMutex type_info_mutex; // NOT recursive
|
BlockingMutex type_info_mutex; // NOT recursive
|
||||||
Array<Type *> type_info_types;
|
Array<Type *> type_info_types;
|
||||||
Map<isize> type_info_map; // Key: Type *
|
PtrMap<Type *, isize> type_info_map;
|
||||||
|
|
||||||
BlockingMutex foreign_mutex; // NOT recursive
|
BlockingMutex foreign_mutex; // NOT recursive
|
||||||
StringMap<Entity *> foreigns;
|
StringMap<Entity *> foreigns;
|
||||||
|
|||||||
@@ -277,6 +277,7 @@ gb_global bool global_module_path_set = false;
|
|||||||
|
|
||||||
#include "string_map.cpp"
|
#include "string_map.cpp"
|
||||||
#include "map.cpp"
|
#include "map.cpp"
|
||||||
|
#include "ptr_map.cpp"
|
||||||
#include "ptr_set.cpp"
|
#include "ptr_set.cpp"
|
||||||
#include "string_set.cpp"
|
#include "string_set.cpp"
|
||||||
#include "priority_queue.cpp"
|
#include "priority_queue.cpp"
|
||||||
|
|||||||
+318
@@ -0,0 +1,318 @@
|
|||||||
|
#define PTR_MAP_ENABLE_MULTI_MAP 1
|
||||||
|
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
struct PtrMapEntry {
|
||||||
|
static_assert(sizeof(K) == sizeof(void *), "Key size must be pointer size");
|
||||||
|
|
||||||
|
u32 hash;
|
||||||
|
MapIndex next;
|
||||||
|
K key;
|
||||||
|
V value;
|
||||||
|
};
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
struct PtrMap {
|
||||||
|
Slice<MapIndex> hashes;
|
||||||
|
Array<PtrMapEntry<K, V> > entries;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
template <typename K>
|
||||||
|
u32 ptr_map_hash_key(K key) {
|
||||||
|
return gb_fnv32a(&key, gb_size_of(key));
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V> void map_init (PtrMap<K, V> *h, gbAllocator a, isize capacity = 16);
|
||||||
|
template <typename K, typename V> void map_destroy (PtrMap<K, V> *h);
|
||||||
|
template <typename K, typename V> V * map_get (PtrMap<K, V> *h, K key);
|
||||||
|
template <typename K, typename V> void map_set (PtrMap<K, V> *h, K key, V const &value);
|
||||||
|
template <typename K, typename V> void map_remove (PtrMap<K, V> *h, K key);
|
||||||
|
template <typename K, typename V> void map_clear (PtrMap<K, V> *h);
|
||||||
|
template <typename K, typename V> void map_grow (PtrMap<K, V> *h);
|
||||||
|
template <typename K, typename V> void map_rehash (PtrMap<K, V> *h, isize new_count);
|
||||||
|
template <typename K, typename V> void map_reserve (PtrMap<K, V> *h, isize cap);
|
||||||
|
|
||||||
|
#if PTR_MAP_ENABLE_MULTI_MAP
|
||||||
|
// Mutlivalued map procedure
|
||||||
|
template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_first(PtrMap<K, V> *h, K key);
|
||||||
|
template <typename K, typename V> PtrMapEntry<K, V> * multi_map_find_next (PtrMap<K, V> *h, PtrMapEntry<K, V> *e);
|
||||||
|
|
||||||
|
template <typename K, typename V> isize multi_map_count (PtrMap<K, V> *h, K key);
|
||||||
|
template <typename K, typename V> void multi_map_get_all (PtrMap<K, V> *h, K key, V *items);
|
||||||
|
template <typename K, typename V> void multi_map_insert (PtrMap<K, V> *h, K key, V const &value);
|
||||||
|
template <typename K, typename V> void multi_map_remove (PtrMap<K, V> *h, K key, PtrMapEntry<K, V> *e);
|
||||||
|
template <typename K, typename V> void multi_map_remove_all(PtrMap<K, V> *h, K key);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_inline void map_init(PtrMap<K, V> *h, gbAllocator a, isize capacity) {
|
||||||
|
capacity = next_pow2_isize(capacity);
|
||||||
|
slice_init(&h->hashes, a, capacity);
|
||||||
|
array_init(&h->entries, a, 0, capacity);
|
||||||
|
for (isize i = 0; i < capacity; i++) {
|
||||||
|
h->hashes.data[i] = MAP_SENTINEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_inline void map_destroy(PtrMap<K, V> *h) {
|
||||||
|
slice_free(&h->hashes, h->entries.allocator);
|
||||||
|
array_free(&h->entries);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_internal MapIndex map__add_entry(PtrMap<K, V> *h, K key) {
|
||||||
|
PtrMapEntry<K, V> e = {};
|
||||||
|
e.hash = ptr_map_hash_key(key);
|
||||||
|
e.key = key;
|
||||||
|
e.next = MAP_SENTINEL;
|
||||||
|
array_add(&h->entries, e);
|
||||||
|
return cast(MapIndex)(h->entries.count-1);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_internal MapFindResult map__find(PtrMap<K, V> *h, K key) {
|
||||||
|
MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
|
||||||
|
if (h->hashes.count == 0) {
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
u32 hash = ptr_map_hash_key(key);
|
||||||
|
fr.hash_index = cast(MapIndex)(hash & (h->hashes.count-1));
|
||||||
|
fr.entry_index = h->hashes.data[fr.hash_index];
|
||||||
|
while (fr.entry_index != MAP_SENTINEL) {
|
||||||
|
if (h->entries.data[fr.entry_index].key == key) {
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
fr.entry_prev = fr.entry_index;
|
||||||
|
fr.entry_index = h->entries.data[fr.entry_index].next;
|
||||||
|
}
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_internal MapFindResult map__find_from_entry(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
|
||||||
|
MapFindResult fr = {MAP_SENTINEL, MAP_SENTINEL, MAP_SENTINEL};
|
||||||
|
if (h->hashes.count == 0) {
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
fr.hash_index = cast(MapIndex)(e->hash & (h->hashes.count-1));
|
||||||
|
fr.entry_index = h->hashes.data[fr.hash_index];
|
||||||
|
while (fr.entry_index != MAP_SENTINEL) {
|
||||||
|
if (&h->entries.data[fr.entry_index] == e) {
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
fr.entry_prev = fr.entry_index;
|
||||||
|
fr.entry_index = h->entries.data[fr.entry_index].next;
|
||||||
|
}
|
||||||
|
return fr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_internal b32 map__full(PtrMap<K, V> *h) {
|
||||||
|
return 0.75f * h->hashes.count <= h->entries.count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_inline void map_grow(PtrMap<K, V> *h) {
|
||||||
|
isize new_count = gb_max(h->hashes.count<<1, 16);
|
||||||
|
map_rehash(h, new_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void map_reset_entries(PtrMap<K, V> *h) {
|
||||||
|
for (isize i = 0; i < h->hashes.count; i++) {
|
||||||
|
h->hashes.data[i] = MAP_SENTINEL;
|
||||||
|
}
|
||||||
|
for (isize i = 0; i < h->entries.count; i++) {
|
||||||
|
MapFindResult fr;
|
||||||
|
PtrMapEntry<K, V> *e = &h->entries.data[i];
|
||||||
|
e->next = MAP_SENTINEL;
|
||||||
|
fr = map__find_from_entry(h, e);
|
||||||
|
if (fr.entry_prev == MAP_SENTINEL) {
|
||||||
|
h->hashes[fr.hash_index] = cast(MapIndex)i;
|
||||||
|
} else {
|
||||||
|
h->entries[fr.entry_prev].next = cast(MapIndex)i;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void map_reserve(PtrMap<K, V> *h, isize cap) {
|
||||||
|
array_reserve(&h->entries, cap);
|
||||||
|
if (h->entries.count*2 < h->hashes.count) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
slice_resize(&h->hashes, h->entries.allocator, cap*2);
|
||||||
|
map_reset_entries(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void map_rehash(PtrMap<K, V> *h, isize new_count) {
|
||||||
|
map_reserve(h, new_count);
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
V *map_get(PtrMap<K, V> *h, K key) {
|
||||||
|
isize index = map__find(h, key).entry_index;
|
||||||
|
if (index != MAP_SENTINEL) {
|
||||||
|
return &h->entries.data[index].value;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
V &map_must_get(PtrMap<K, V> *h, K key) {
|
||||||
|
isize index = map__find(h, key).entry_index;
|
||||||
|
GB_ASSERT(index != MAP_SENTINEL);
|
||||||
|
return h->entries.data[index].value;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void map_set(PtrMap<K, V> *h, K key, V const &value) {
|
||||||
|
MapIndex index;
|
||||||
|
MapFindResult fr;
|
||||||
|
if (h->hashes.count == 0) {
|
||||||
|
map_grow(h);
|
||||||
|
}
|
||||||
|
fr = map__find(h, key);
|
||||||
|
if (fr.entry_index != MAP_SENTINEL) {
|
||||||
|
index = fr.entry_index;
|
||||||
|
} else {
|
||||||
|
index = map__add_entry(h, key);
|
||||||
|
if (fr.entry_prev != MAP_SENTINEL) {
|
||||||
|
h->entries.data[fr.entry_prev].next = index;
|
||||||
|
} else {
|
||||||
|
h->hashes.data[fr.hash_index] = index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
h->entries.data[index].value = value;
|
||||||
|
|
||||||
|
if (map__full(h)) {
|
||||||
|
map_grow(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void map__erase(PtrMap<K, V> *h, MapFindResult const &fr) {
|
||||||
|
MapFindResult last;
|
||||||
|
if (fr.entry_prev == MAP_SENTINEL) {
|
||||||
|
h->hashes.data[fr.hash_index] = h->entries.data[fr.entry_index].next;
|
||||||
|
} else {
|
||||||
|
h->entries.data[fr.entry_prev].next = h->entries.data[fr.entry_index].next;
|
||||||
|
}
|
||||||
|
if (fr.entry_index == h->entries.count-1) {
|
||||||
|
array_pop(&h->entries);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
h->entries.data[fr.entry_index] = h->entries.data[h->entries.count-1];
|
||||||
|
array_pop(&h->entries);
|
||||||
|
|
||||||
|
last = map__find(h, h->entries.data[fr.entry_index].key);
|
||||||
|
if (last.entry_prev != MAP_SENTINEL) {
|
||||||
|
h->entries.data[last.entry_prev].next = fr.entry_index;
|
||||||
|
} else {
|
||||||
|
h->hashes.data[last.hash_index] = fr.entry_index;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void map_remove(PtrMap<K, V> *h, HashKey const &key) {
|
||||||
|
MapFindResult fr = map__find(h, key);
|
||||||
|
if (fr.entry_index != MAP_SENTINEL) {
|
||||||
|
map__erase(h, fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
gb_inline void map_clear(PtrMap<K, V> *h) {
|
||||||
|
array_clear(&h->entries);
|
||||||
|
for (isize i = 0; i < h->hashes.count; i++) {
|
||||||
|
h->hashes.data[i] = MAP_SENTINEL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if PTR_MAP_ENABLE_MULTI_MAP
|
||||||
|
template <typename K, typename V>
|
||||||
|
PtrMapEntry<K, V> *multi_map_find_first(PtrMap<K, V> *h, HashKey const &key) {
|
||||||
|
isize i = map__find(h, key).entry_index;
|
||||||
|
if (i == MAP_SENTINEL) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return &h->entries.data[i];
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
PtrMapEntry<K, V> *multi_map_find_next(PtrMap<K, V> *h, PtrMapEntry<K, V> *e) {
|
||||||
|
isize i = e->next;
|
||||||
|
while (i != MAP_SENTINEL) {
|
||||||
|
if (hash_key_equal(h->entries.data[i].key, e->key)) {
|
||||||
|
return &h->entries.data[i];
|
||||||
|
}
|
||||||
|
i = h->entries.data[i].next;
|
||||||
|
}
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
isize multi_map_count(PtrMap<K, V> *h, HashKey const &key) {
|
||||||
|
isize count = 0;
|
||||||
|
PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
|
||||||
|
while (e != nullptr) {
|
||||||
|
count++;
|
||||||
|
e = multi_map_find_next(h, e);
|
||||||
|
}
|
||||||
|
return count;
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void multi_map_get_all(PtrMap<K, V> *h, K key, V *items) {
|
||||||
|
isize i = 0;
|
||||||
|
PtrMapEntry<K, V> *e = multi_map_find_first(h, key);
|
||||||
|
while (e != nullptr) {
|
||||||
|
items[i++] = e->value;
|
||||||
|
e = multi_map_find_next(h, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void multi_map_insert(PtrMap<K, V> *h, K key, V const &value) {
|
||||||
|
MapFindResult fr;
|
||||||
|
MapIndex i;
|
||||||
|
if (h->hashes.count == 0) {
|
||||||
|
map_grow(h);
|
||||||
|
}
|
||||||
|
// Make
|
||||||
|
fr = map__find(h, key);
|
||||||
|
i = map__add_entry(h, key);
|
||||||
|
if (fr.entry_prev == MAP_SENTINEL) {
|
||||||
|
h->hashes.data[fr.hash_index] = i;
|
||||||
|
} else {
|
||||||
|
h->entries.data[fr.entry_prev].next = i;
|
||||||
|
}
|
||||||
|
h->entries.data[i].next = fr.entry_index;
|
||||||
|
h->entries.data[i].value = value;
|
||||||
|
// Grow if needed
|
||||||
|
if (map__full(h)) {
|
||||||
|
map_grow(h);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void multi_map_remove(PtrMap<K, V> *h, HashKey const &key, PtrMapEntry<K, V> *e) {
|
||||||
|
MapFindResult fr = map__find_from_entry(h, e);
|
||||||
|
if (fr.entry_index != MAP_SENTINEL) {
|
||||||
|
map__erase(h, fr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
template <typename K, typename V>
|
||||||
|
void multi_map_remove_all(PtrMap<K, V> *h, HashKey const &key) {
|
||||||
|
while (map_get(h, key) != nullptr) {
|
||||||
|
map_remove(h, key);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
Reference in New Issue
Block a user