49 inline uint32_t
memHash(
const char* val,
int len)
52 uint64_t val64[4]; val64[0] = 0;
53 memcpy(&val64[0], &val[len64], len & 7);
54 uint64_t hashval[4] = {0,0,0,0};
55 hashval[0] = val64[0]*16777619;
57 for (
int i = 0; i+32 <= len64; i+=32) {
58 for (
int j = 0; j < 4; ++j) {
59 memcpy(&val64[j], &val[i+j*8], 8);
60 hashval[j] = (hashval[j]*16777619) ^ val64[j];
63 hashval[0] = (hashval[0]*16777619) ^ hashval[1];
64 hashval[2] = (hashval[2]*16777619) ^ hashval[3];
65 hashval[0] = (hashval[0]*16777619) ^ hashval[2];
66 return uint32_t(hashval[0]);
69 inline bool memCompare(
const char* a,
const char* b,
int len)
73 for (
int i = 0; i < len64; i+=8) {
74 memcpy(&val64[0], &a[i], 8);
75 memcpy(&val64[1], &b[i], 8);
76 if (val64[0] != val64[1])
return 1;
78 return memcmp(&a[len64], &b[len64], len & 7);
93 StringKey() : _val(0), _len(0), _hash(0), _ownsVal(false) {}
97 _len = uint32_t(strlen(val));
106 char* newval =
new char[key.
_len+1];
107 memcpy(newval, key.
_val, key.
_len+1);
147 uint32_t
hash()
volatile {
return (_val*7919) & ~0xf; }
150 template <
typename Key,
typename Value>
169 _entries =
new Entry[_numEntries];
174 for (uint32_t i = 0; i < _numEntries; ++i) {
175 if (_entries[i].value)
delete _entries[i].value;
178 for (
size_t i = 0; i < _oldEntries.size(); ++i) {
179 delete [] _oldEntries[i];
181 std::vector<Entry*>().swap(_oldEntries);
201 uint32_t
size()
const {
return _size; }
205 uint32_t mask = _numEntries-1;
206 Entry* entries = getEntries();
207 uint32_t
hash = key.hash();
210 for (uint32_t i = hash;; ++i) {
211 Entry& e = entries[i & mask];
212 if (e.key.matches(key)) {
224 Value
tryInsert(Key& key, Value value,
size_t& newMemUsed)
226 Entry* entries = lockEntriesAndGrowIfNeeded(newMemUsed);
227 uint32_t mask = _numEntries-1;
228 uint32_t
hash = key.hash();
231 for (uint32_t i = hash;; ++i) {
232 Entry& e = entries[i & mask];
241 while (e.key.isEmpty()) ;
242 if (e.key.matches(key)) {
247 unlockEntries(entries);
251 template <
typename Fn>
254 Entry* entries = getEntries();
255 for (uint32_t i = 0; i < _numEntries; ++i) {
256 Value v = entries[i].value;
265 Entry* entries = _entries;
266 if (entries)
return entries;
273 Entry* entries = _entries;
287 Entry* entries = lockEntries();
288 if (_size*2 >= _numEntries) {
289 entries = grow(entries, newMemUsed);
294 Entry*
grow(Entry* oldEntries,
size_t& newMemUsed)
296 _oldEntries.push_back(oldEntries);
297 uint32_t numNewEntries = _numEntries*2;
298 Entry* entries =
new Entry[numNewEntries];
299 newMemUsed = numNewEntries *
sizeof(Entry);
300 uint32_t mask = numNewEntries-1;
301 for (uint32_t oldIndex = 0; oldIndex < _numEntries; ++oldIndex) {
302 Entry& oldEntry = oldEntries[oldIndex];
303 if (oldEntry.value) {
304 for (
int newIndex = oldEntry.key.hash();; ++newIndex) {
305 Entry& newEntry = entries[newIndex&mask];
306 if (!newEntry.value) {
307 newEntry.key.move(oldEntry.key);
308 newEntry.value = oldEntry.value;
314 _numEntries = numNewEntries;
std::vector< Entry * > _oldEntries
Entry * grow(Entry *oldEntries, size_t &newMemUsed)
void unlockEntries(Entry *entries)
void operator=(const StringKey &key)
bool matches(const IntKey &key) volatile
uint32_t volatile _numEntries
bool memCompare(const char *a, const char *b, int len)
void copy(volatile StringKey &key) volatile
PTEX_NAMESPACE_BEGIN uint32_t memHash(const char *val, int len)
void move(volatile IntKey &key) volatile
const char *volatile _val
Entry * lockEntriesAndGrowIfNeeded(size_t &newMemUsed)
StringKey(const char *val)
void copy(volatile IntKey &key) volatile
bool matches(const StringKey &key) volatile
#define PTEX_NAMESPACE_END
Value tryInsert(Key &key, Value value, size_t &newMemUsed)
void move(volatile StringKey &key) volatile