7template <
typename Object>
11 if (mPages !=
nullptr)
14 JPH_ASSERT(mNumFreeObjects.load(memory_order_relaxed) == mNumPages * mPageSize);
17 uint32 num_pages = mNumObjectsAllocated / mPageSize;
18 for (
uint32 page = 0; page < num_pages; ++page)
24template <
typename Object>
32 mNumPages = (inMaxObjects + inPageSize - 1) / inPageSize;
33 mPageSize = inPageSize;
35 mObjectMask = inPageSize - 1;
39 mPages =
reinterpret_cast<ObjectStorage **
>(
Allocate(mNumPages *
sizeof(ObjectStorage *)));
42 mNumObjectsAllocated = 0;
43 mFirstFreeObjectInNewPage = 0;
49 mFirstFreeObjectAndTag = cInvalidObjectIndex;
52template <
typename Object>
53template <
typename... Parameters>
59 uint64 first_free_object_and_tag = mFirstFreeObjectAndTag.load(memory_order_acquire);
61 if (first_free == cInvalidObjectIndex)
64 first_free = mFirstFreeObjectInNewPage.fetch_add(1, memory_order_relaxed);
65 if (first_free >= mNumObjectsAllocated)
68 lock_guard lock(mPageMutex);
69 while (first_free >= mNumObjectsAllocated)
71 uint32 next_page = mNumObjectsAllocated / mPageSize;
72 if (next_page == mNumPages)
73 return cInvalidObjectIndex;
75 mNumObjectsAllocated += mPageSize;
81 ObjectStorage &storage = GetStorage(first_free);
82 ::new (&storage.mObject)
Object(
std::forward<Parameters>(inParameters)...);
83 storage.mNextFreeObject.store(first_free, memory_order_release);
89 uint32 new_first_free = GetStorage(first_free).mNextFreeObject.load(memory_order_acquire);
92 uint64 new_first_free_object_and_tag =
uint64(new_first_free) + (
uint64(mAllocationTag.fetch_add(1, memory_order_relaxed)) << 32);
95 if (mFirstFreeObjectAndTag.compare_exchange_weak(first_free_object_and_tag, new_first_free_object_and_tag, memory_order_release))
99 ObjectStorage &storage = GetStorage(first_free);
100 ::new (&storage.mObject)
Object(std::forward<Parameters>(inParameters)...);
101 storage.mNextFreeObject.store(first_free, memory_order_release);
108template <
typename Object>
114 atomic<uint32> &next_free_object = GetStorage(inObjectIndex).mNextFreeObject;
115 JPH_ASSERT(next_free_object.load(memory_order_relaxed) == inObjectIndex,
"Trying to add a object to the batch that is already in a free list");
116 next_free_object.store(cInvalidObjectIndex, memory_order_release);
122 GetStorage(ioBatch.
mLastObjectIndex).mNextFreeObject.store(inObjectIndex, memory_order_release);
127template <
typename Object>
133 if constexpr (!is_trivially_destructible<Object>())
138 ObjectStorage &storage = GetStorage(object_idx);
139 storage.mObject.~Object();
140 object_idx = storage.mNextFreeObject.load(memory_order_relaxed);
142 while (object_idx != cInvalidObjectIndex);
150 uint64 first_free_object_and_tag = mFirstFreeObjectAndTag.load(memory_order_acquire);
154 storage.mNextFreeObject.store(first_free, memory_order_release);
160 if (mFirstFreeObjectAndTag.compare_exchange_weak(first_free_object_and_tag, new_first_free_object_and_tag, memory_order_release))
166#ifdef JPH_ENABLE_ASSERTS
175template <
typename Object>
178 JPH_ASSERT(inObjectIndex != cInvalidObjectIndex);
181 ObjectStorage &storage = GetStorage(inObjectIndex);
182 storage.mObject.~Object();
188 uint64 first_free_object_and_tag = mFirstFreeObjectAndTag.load(memory_order_acquire);
192 storage.mNextFreeObject.store(first_free, memory_order_release);
195 uint64 new_first_free_object_and_tag =
uint64(inObjectIndex) + (
uint64(mAllocationTag.fetch_add(1, memory_order_relaxed)) << 32);
198 if (mFirstFreeObjectAndTag.compare_exchange_weak(first_free_object_and_tag, new_first_free_object_and_tag, memory_order_release))
207template<
typename Object>
210 uint32 index =
reinterpret_cast<ObjectStorage *
>(inObject)->mNextFreeObject.load(memory_order_relaxed);
212 DestructObject(index);
#define JPH_CACHE_LINE_SIZE
Definition Core.h:493
std::uint64_t uint64
Definition Core.h:457
unsigned int uint
Definition Core.h:453
#define JPH_NAMESPACE_END
Definition Core.h:379
std::uint32_t uint32
Definition Core.h:456
#define JPH_NAMESPACE_BEGIN
Definition Core.h:373
#define JPH_IF_ENABLE_ASSERTS(...)
Definition IssueReporting.h:35
#define JPH_ASSERT(...)
Definition IssueReporting.h:33
constexpr bool IsPowerOf2(T inV)
Check if inV is a power of 2.
Definition Math.h:73
uint CountTrailingZeros(uint32 inValue)
Compute number of trailing zero bits (how many low bits are zero)
Definition Math.h:95
AllocateFunction Allocate
Definition Memory.cpp:68
FreeFunction Free
Definition Memory.cpp:70
AlignedFreeFunction AlignedFree
Definition Memory.cpp:72
AlignedAllocateFunction AlignedAllocate
Definition Memory.cpp:71
@ Object
Start of a new object.
void Init(uint inMaxObjects, uint inPageSize)
Initialize the free list, up to inMaxObjects can be allocated.
Definition FixedSizeFreeList.inl:25
void DestructObjectBatch(Batch &ioBatch)
Lockless destruct batch of objects.
Definition FixedSizeFreeList.inl:128
uint32 ConstructObject(Parameters &&... inParameters)
Lockless construct a new object, inParameters are passed on to the constructor.
Definition FixedSizeFreeList.inl:54
~FixedSizeFreeList()
Destructor.
Definition FixedSizeFreeList.inl:8
void DestructObject(uint32 inObjectIndex)
Lockless destruct an object and return it to the free pool.
Definition FixedSizeFreeList.inl:176
void AddObjectToBatch(Batch &ioBatch, uint32 inObjectIndex)
Definition FixedSizeFreeList.inl:109
A batch of objects that can be destructed.
Definition FixedSizeFreeList.h:99
uint32 mFirstObjectIndex
Definition FixedSizeFreeList.h:100
uint32 mNumObjects
Definition FixedSizeFreeList.h:102
uint32 mLastObjectIndex
Definition FixedSizeFreeList.h:101