22 mObjectStoreSizeBytes = inObjectStoreSizeBytes;
23 mObjectStore =
reinterpret_cast<uint8 *
>(JPH::AlignedAllocate(inObjectStoreSizeBytes, 16));
38 if (mWriteOffset.load(memory_order_relaxed) >= mObjectStoreSizeBytes)
42 uint32 begin = mWriteOffset.fetch_add(inBlockSize, memory_order_relaxed);
43 uint32 end = min(begin + inBlockSize, mObjectStoreSizeBytes);
53 begin = min(begin, mObjectStoreSizeBytes);
64 const uint8 *data =
reinterpret_cast<const uint8 *
>(inData);
65 JPH_ASSERT(data >= mObjectStore && data < mObjectStore + mObjectStoreSizeBytes);
66 return uint32(data - mObjectStore);
73 return reinterpret_cast<T *
>(mObjectStore + inOffset);
81 mAllocator(inAllocator),
82 mBlockSize(inBlockSize)
90 uint32 alignment_mask = inAlignment - 1;
91 uint32 alignment = (inAlignment - (mBegin & alignment_mask)) & alignment_mask;
94 if (mEnd - mBegin < inSize + alignment)
97 mAllocator.
Allocate(mBlockSize, mBegin, mEnd);
100 alignment = (inAlignment - (mBegin & alignment_mask)) & alignment_mask;
103 if (mEnd - mBegin < inSize + alignment)
109 outWriteOffset = mBegin;
118template <
class Key,
class Value>
124 mNumBuckets = inMaxBuckets;
125 mMaxBuckets = inMaxBuckets;
127 mBuckets =
reinterpret_cast<atomic<uint32> *
>(
AlignedAllocate(inMaxBuckets *
sizeof(atomic<uint32>), 16));
132template <
class Key,
class Value>
138template <
class Key,
class Value>
141#ifdef JPH_ENABLE_ASSERTS
147 static_assert(
sizeof(atomic<uint32>) ==
sizeof(
uint32));
150 const uint32 *end = start + mNumBuckets;
159template <
class Key,
class Value>
166 mNumBuckets = inNumBuckets;
169template <
class Key,
class Value>
170template <
class... Params>
174 JPH_ASSERT(Find(inKey, inKeyHash) ==
nullptr);
184#ifdef JPH_ENABLE_ASSERTS
186 mNumKeyValues.fetch_add(1, memory_order_relaxed);
190 KeyValue *kv = mAllocator.template FromOffset<KeyValue>(write_offset);
193 memset(kv, 0xcd, size);
196 new (&kv->mValue) Value(std::forward<Params>(inConstructorParams)...);
199 atomic<uint32> &offset = mBuckets[inKeyHash & (mNumBuckets - 1)];
202 uint32 old_offset = offset.load(memory_order_relaxed);
205 kv->mNextOffset = old_offset;
206 if (offset.compare_exchange_weak(old_offset, write_offset, memory_order_release))
213template <
class Key,
class Value>
217 uint32 offset = mBuckets[inKeyHash & (mNumBuckets - 1)].load(memory_order_acquire);
218 while (offset != cInvalidHandle)
221 const KeyValue *kv = mAllocator.template FromOffset<const KeyValue>(offset);
222 if (kv->mKey == inKey)
224 offset = kv->mNextOffset;
231template <
class Key,
class Value>
234 return mAllocator.ToOffset(inKeyValue);
237template <
class Key,
class Value>
240 return mAllocator.template FromOffset<const KeyValue>(inHandle);
243template <
class Key,
class Value>
246 for (
const atomic<uint32> *bucket = mBuckets; bucket < mBuckets + mNumBuckets; ++bucket)
249 while (offset != cInvalidHandle)
251 const KeyValue *kv = mAllocator.template FromOffset<const KeyValue>(offset);
253 offset = kv->mNextOffset;
258template <
class Key,
class Value>
262 Iterator it {
this, 0, mBuckets[0] };
265 if (it.mOffset == cInvalidHandle)
271template <
class Key,
class Value>
274 return {
this, mNumBuckets, cInvalidHandle };
277template <
class Key,
class Value>
282 return *
mMap->mAllocator.template FromOffset<KeyValue>(
mOffset);
285template <
class Key,
class Value>
293 const KeyValue *kv = mMap->mAllocator.template FromOffset<const KeyValue>(mOffset);
294 mOffset = kv->mNextOffset;
304 if (mBucket >= mMap->mNumBuckets)
308 mOffset = mMap->mBuckets[mBucket];
316template <
class Key,
class Value>
319 const int cMaxPerBucket = 256;
321 int max_objects_per_bucket = 0;
323 int histogram[cMaxPerBucket];
324 for (
int i = 0; i < cMaxPerBucket; ++i)
327 for (atomic<uint32> *bucket = mBuckets, *bucket_end = mBuckets + mNumBuckets; bucket < bucket_end; ++bucket)
329 int objects_in_bucket = 0;
333 const KeyValue *kv = mAllocator.template FromOffset<const KeyValue>(offset);
334 offset = kv->mNextOffset;
338 max_objects_per_bucket = max(objects_in_bucket, max_objects_per_bucket);
339 histogram[min(objects_in_bucket, cMaxPerBucket - 1)]++;
342 Trace(
"max_objects_per_bucket = %d, num_buckets = %u, num_objects = %d", max_objects_per_bucket, mNumBuckets, num_objects);
344 for (
int i = 0; i < cMaxPerBucket; ++i)
345 if (histogram[i] != 0)
346 Trace(
"%d: %d", i, histogram[i]);
std::uint8_t uint8
Definition Core.h:482
std::uint64_t uint64
Definition Core.h:485
unsigned int uint
Definition Core.h:481
#define JPH_NAMESPACE_END
Definition Core.h:414
std::uint32_t uint32
Definition Core.h:484
#define JPH_NAMESPACE_BEGIN
Definition Core.h:408
TraceFunction Trace
Definition IssueReporting.cpp:14
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
constexpr bool IsPowerOf2(T inV)
Check if inV is a power of 2.
Definition Math.h:76
bool IsAligned(T inV, uint64 inAlignment)
Check if inV is inAlignment aligned.
Definition Math.h:91
AlignedFreeFunction AlignedFree
Definition Memory.cpp:72
AlignedAllocateFunction AlignedAllocate
Definition Memory.cpp:71
void push_back(const T &inValue)
Add element to the back of the array.
Definition Array.h:277
Definition LockFreeHashMap.h:49
LFHMAllocatorContext(LFHMAllocator &inAllocator, uint32 inBlockSize)
Construct a new allocator context.
Definition LockFreeHashMap.inl:80
bool Allocate(uint32 inSize, uint32 inAlignment, uint32 &outWriteOffset)
Allocate data block.
Definition LockFreeHashMap.inl:86
Allocator for a lock free hash map.
Definition LockFreeHashMap.h:14
uint32 ToOffset(const T *inData) const
Convert a pointer to an offset.
Definition LockFreeHashMap.inl:62
~LFHMAllocator()
Destructor.
Definition LockFreeHashMap.inl:13
void Init(uint inObjectStoreSizeBytes)
Definition LockFreeHashMap.inl:18
T * FromOffset(uint32 inOffset) const
Convert an offset to a pointer.
Definition LockFreeHashMap.inl:70
void Allocate(uint32 inBlockSize, uint32 &ioBegin, uint32 &ioEnd)
Definition LockFreeHashMap.inl:31
void Clear()
Clear all allocations.
Definition LockFreeHashMap.inl:26
A key / value pair that is inserted in the map.
Definition LockFreeHashMap.h:100
Definition LockFreeHashMap.h:72
const KeyValue * FromHandle(uint32 inHandle) const
Convert uint32 handle back to key and value.
Definition LockFreeHashMap.inl:238
Iterator begin()
Definition LockFreeHashMap.inl:259
void GetAllKeyValues(Array< const KeyValue * > &outAll) const
Get all key/value pairs.
Definition LockFreeHashMap.inl:244
void Init(uint32 inMaxBuckets)
Definition LockFreeHashMap.inl:119
void SetNumBuckets(uint32 inNumBuckets)
Definition LockFreeHashMap.inl:160
KeyValue * Create(LFHMAllocatorContext &ioContext, const Key &inKey, uint64 inKeyHash, int inExtraBytes, Params &&... inConstructorParams)
Definition LockFreeHashMap.inl:171
~LockFreeHashMap()
Definition LockFreeHashMap.inl:133
const KeyValue * Find(const Key &inKey, uint64 inKeyHash) const
Find an element, returns null if not found.
Definition LockFreeHashMap.inl:214
uint32 ToHandle(const KeyValue *inKeyValue) const
Get convert key value pair to uint32 handle.
Definition LockFreeHashMap.inl:232
Iterator end()
Definition LockFreeHashMap.inl:272
static const uint32 cInvalidHandle
Value of an invalid handle.
Definition LockFreeHashMap.h:123
void Clear()
Definition LockFreeHashMap.inl:139
static JPH_INLINE UVec4 sReplicate(uint32 inV)
Replicate int inV across all components.
Definition UVec4.inl:56
JPH_INLINE void StoreInt4Aligned(uint32 *outV) const
Store 4 ints to memory, aligned to 16 bytes.
Definition UVec4.inl:363
Non-const iterator.
Definition LockFreeHashMap.h:142
uint32 mOffset
Definition LockFreeHashMap.h:155
Iterator & operator++()
Next item.
Definition LockFreeHashMap.inl:286
MapType * mMap
Definition LockFreeHashMap.h:153
KeyValue & operator*()
Convert to key value pair.
Definition LockFreeHashMap.inl:278