|
@@ -45,6 +45,9 @@
|
|
*
|
|
*
|
|
* The entries are stored inplace, so huge keys or values might fill cache lines
|
|
* The entries are stored inplace, so huge keys or values might fill cache lines
|
|
* a lot faster.
|
|
* a lot faster.
|
|
|
|
+ *
|
|
|
|
+ * Only used keys and values are constructed. For free positions there's space
|
|
|
|
+ * in the arrays for each, but that memory is kept uninitialized.
|
|
*/
|
|
*/
|
|
template <class TKey, class TValue,
|
|
template <class TKey, class TValue,
|
|
class Hasher = HashMapHasherDefault,
|
|
class Hasher = HashMapHasherDefault,
|
|
@@ -149,9 +152,9 @@ private:
|
|
uint32_t *old_hashes = hashes;
|
|
uint32_t *old_hashes = hashes;
|
|
|
|
|
|
num_elements = 0;
|
|
num_elements = 0;
|
|
- keys = memnew_arr(TKey, capacity);
|
|
|
|
- values = memnew_arr(TValue, capacity);
|
|
|
|
- hashes = memnew_arr(uint32_t, capacity);
|
|
|
|
|
|
+ keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity));
|
|
|
|
+ values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity));
|
|
|
|
+ hashes = static_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity));
|
|
|
|
|
|
for (uint32_t i = 0; i < capacity; i++) {
|
|
for (uint32_t i = 0; i < capacity; i++) {
|
|
hashes[i] = 0;
|
|
hashes[i] = 0;
|
|
@@ -163,11 +166,14 @@ private:
|
|
}
|
|
}
|
|
|
|
|
|
_insert_with_hash(old_hashes[i], old_keys[i], old_values[i]);
|
|
_insert_with_hash(old_hashes[i], old_keys[i], old_values[i]);
|
|
|
|
+
|
|
|
|
+ old_keys[i].~TKey();
|
|
|
|
+ old_values[i].~TValue();
|
|
}
|
|
}
|
|
|
|
|
|
- memdelete_arr(old_keys);
|
|
|
|
- memdelete_arr(old_values);
|
|
|
|
- memdelete_arr(old_hashes);
|
|
|
|
|
|
+ Memory::free_static(old_keys);
|
|
|
|
+ Memory::free_static(old_values);
|
|
|
|
+ Memory::free_static(old_hashes);
|
|
}
|
|
}
|
|
|
|
|
|
void _resize_and_rehash() {
|
|
void _resize_and_rehash() {
|
|
@@ -214,8 +220,7 @@ public:
|
|
bool exists = _lookup_pos(p_key, pos);
|
|
bool exists = _lookup_pos(p_key, pos);
|
|
|
|
|
|
if (exists) {
|
|
if (exists) {
|
|
- values[pos].~TValue();
|
|
|
|
- memnew_placement(&values[pos], TValue(p_data));
|
|
|
|
|
|
+ values[pos] = p_data;
|
|
} else {
|
|
} else {
|
|
insert(p_key, p_data);
|
|
insert(p_key, p_data);
|
|
}
|
|
}
|
|
@@ -232,8 +237,7 @@ public:
|
|
bool exists = _lookup_pos(p_key, pos);
|
|
bool exists = _lookup_pos(p_key, pos);
|
|
|
|
|
|
if (exists) {
|
|
if (exists) {
|
|
- r_data.~TValue();
|
|
|
|
- memnew_placement(&r_data, TValue(values[pos]));
|
|
|
|
|
|
+ r_data = values[pos];
|
|
return true;
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
@@ -336,9 +340,9 @@ public:
|
|
capacity = p_initial_capacity;
|
|
capacity = p_initial_capacity;
|
|
num_elements = 0;
|
|
num_elements = 0;
|
|
|
|
|
|
- keys = memnew_arr(TKey, p_initial_capacity);
|
|
|
|
- values = memnew_arr(TValue, p_initial_capacity);
|
|
|
|
- hashes = memnew_arr(uint32_t, p_initial_capacity);
|
|
|
|
|
|
+ keys = static_cast<TKey *>(Memory::alloc_static(sizeof(TKey) * capacity));
|
|
|
|
+ values = static_cast<TValue *>(Memory::alloc_static(sizeof(TValue) * capacity));
|
|
|
|
+ hashes = static_cast<uint32_t *>(Memory::alloc_static(sizeof(uint32_t) * capacity));
|
|
|
|
|
|
for (uint32_t i = 0; i < p_initial_capacity; i++) {
|
|
for (uint32_t i = 0; i < p_initial_capacity; i++) {
|
|
hashes[i] = EMPTY_HASH;
|
|
hashes[i] = EMPTY_HASH;
|
|
@@ -347,9 +351,19 @@ public:
|
|
|
|
|
|
~OAHashMap() {
|
|
~OAHashMap() {
|
|
|
|
|
|
- memdelete_arr(keys);
|
|
|
|
- memdelete_arr(values);
|
|
|
|
- memdelete_arr(hashes);
|
|
|
|
|
|
+ for (uint32_t i = 0; i < capacity; i++) {
|
|
|
|
+
|
|
|
|
+ if (hashes[i] == EMPTY_HASH) {
|
|
|
|
+ continue;
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ values[i].~TValue();
|
|
|
|
+ keys[i].~TKey();
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ Memory::free_static(keys);
|
|
|
|
+ Memory::free_static(values);
|
|
|
|
+ Memory::free_static(hashes);
|
|
}
|
|
}
|
|
};
|
|
};
|
|
|
|
|