50 inline bool memCompare(
const char* a,
const char* b,
int len)
54 for (
int i = 0; i < len64; i+=8) {
55 memcpy(&val64[0], &a[i], 8);
56 memcpy(&val64[1], &b[i], 8);
57 if (val64[0] != val64[1])
return 1;
59 return memcmp(&a[len64], &b[len64], len & 7);
74 StringKey() : _val(0), _len(0), _ownsVal(false), _hash(0) {}
78 _len = uint16_t(strlen(val));
79 _hash = uint32_t(std::hash<std::string_view>{}(std::string_view(_val, _len)));
87 char* newval =
new char[key.
_len+1];
88 memcpy(newval, key.
_val, key.
_len+1);
109 bool isEmpty()
const volatile {
return _val==0; }
127 bool isEmpty()
volatile const {
return _val==0; }
128 uint32_t
hash()
volatile const {
return (_val*7919) & ~0xf; }
131 template <
typename Key,
typename Value>
165 for (uint32_t i = 0; i < header->numEntries; ++i) {
166 entries[i].key.~Key();
167 if (entries[i].value)
delete entries[i].value;
170 for (
size_t i = 0; i <
_oldTables.size(); ++i) {
194 return ((TableHeader*)
_table)->size;
197 Value
get(Key& key)
const
199 const TableHeader* header;
200 const Entry* entries;
202 uint32_t mask = header->numEntries-1;
203 uint32_t hash = key.hash();
206 for (uint32_t i = hash;; ++i) {
207 const Entry& e = entries[i & mask];
208 if (e.key.matches(key)) {
220 Value
tryInsert(Key& key, Value value,
size_t& newMemUsed)
226 uint32_t mask = header->numEntries-1;
227 uint32_t hash = key.hash();
230 for (uint32_t i = hash;; ++i) {
231 Entry& e = entries[i & mask];
240 while (e.key.isEmpty()) ;
241 if (e.key.matches(key)) {
250 template <
typename Fn>
251 void foreach(Fn& fn)
const
253 const TableHeader* header;
254 const Entry* entries;
256 for (uint32_t i = 0; i < header->numEntries; ++i) {
257 Value v = entries[i].value;
265 memsize =
sizeof(TableHeader) +
sizeof(Entry) * numEntries;
266 void* table = malloc(memsize);
267 memset(table, 0, memsize);
268 TableHeader* header =
new (table) TableHeader;
269 header->numEntries = numEntries;
271 Entry* entries = (Entry*)((
char*)table +
sizeof(TableHeader));
272 for (int32_t i = 0; i < numEntries; ++i)
274 new (&entries[i]) Entry();
279 static void getTable(
const void* table,
const TableHeader*& header,
const Entry*& entries)
281 header = (
const TableHeader*) table;
282 entries = (
const Entry*)((
const char*)table +
sizeof(TableHeader));
285 static void getTable(
void* table, TableHeader*& header, Entry*& entries)
287 header = (TableHeader*) table;
288 entries = (Entry*)((
char*)table +
sizeof(TableHeader));
305 if (header->size*2 >= header->numEntries) {
306 table =
grow(table, newMemUsed);
311 void*
grow(
void* oldTable,
size_t& newMemUsed)
313 TableHeader* oldHeader;
315 getTable(oldTable, oldHeader, oldEntries);
318 void* newTable =
allocTable(oldHeader->numEntries*2, newMemUsed);
319 TableHeader* newHeader;
321 getTable(newTable, newHeader, newEntries);
322 uint32_t mask = newHeader->numEntries-1;
323 for (uint32_t oldIndex = 0; oldIndex < oldHeader->numEntries; ++oldIndex) {
324 Entry& oldEntry = oldEntries[oldIndex];
325 if (oldEntry.value) {
326 for (
int newIndex = oldEntry.key.hash();; ++newIndex) {
327 Entry& newEntry = newEntries[newIndex&mask];
328 if (!newEntry.value) {
329 newEntry.key.move(oldEntry.key);
330 newEntry.value = oldEntry.value;
336 newHeader->size = oldHeader->size;
bool matches(const StringKey &key) const volatile
static void getTable(void *table, TableHeader *&header, Entry *&entries)
void operator=(const StringKey &key)
bool isEmpty() const volatile
void * lockTableAndGrowIfNeeded(size_t &newMemUsed)
uint32_t hash() volatile const
void unlockTable(void *table)
void * grow(void *oldTable, size_t &newMemUsed)
void copy(volatile StringKey &key) volatile
void * allocTable(int32_t numEntries, size_t &memsize)
uint32_t hash() const volatile
void move(volatile IntKey &key) volatile
void operator=(const PtexHashMap &)
const char *volatile _val
PTEX_NAMESPACE_BEGIN bool memCompare(const char *a, const char *b, int len)
StringKey(const char *val)
void operator=(const Entry &)
uint16_t volatile _ownsVal
bool matches(const IntKey &key) const volatile
void copy(volatile IntKey &key) volatile
static void getTable(const void *table, const TableHeader *&header, const Entry *&entries)
bool isEmpty() volatile const
#define PTEX_NAMESPACE_END
std::vector< void * > _oldTables
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
void move(volatile StringKey &key) volatile