void PtrTable::realloc(PxU32 oldCapacity, PxU32 newCapacity, PtrTableStorageManager& sm) { PX_ASSERT((mOwnsMemory && oldCapacity) || (!mOwnsMemory && oldCapacity == 0)); PX_ASSERT(newCapacity); if(mOwnsMemory && sm.canReuse(oldCapacity, newCapacity)) return; void** newMem = sm.allocate(newCapacity * sizeof(void*)); PxMemCopy(newMem, mList, mCount * sizeof(void*)); if(mOwnsMemory) sm.deallocate(mList, oldCapacity*sizeof(void*)); mList = newMem; mOwnsMemory = true; }
void PtrTable::clear(PtrTableStorageManager& sm) { if(mOwnsMemory && mCount>1) { PxU32 implicitCapacity = Ps::nextPowerOfTwo(PxU32(mCount)-1); sm.deallocate(mList, sizeof(void*)*implicitCapacity); } mList = NULL; mOwnsMemory = true; mCount = 0; }
void PtrTable::replaceWithLast(PxU32 index, PtrTableStorageManager& sm) { PX_ASSERT(mCount!=0); if(mCount == 1) // 1 -> 0 easy case { PX_ASSERT(mOwnsMemory); PX_ASSERT(mBufferUsed); mList = NULL; mCount = 0; mBufferUsed = false; } else if(mCount == 2) // 2 -> 1 easy case { PX_ASSERT(!mBufferUsed); void *ptr = mList[1-index]; if(mOwnsMemory) sm.deallocate(mList, 2*sizeof(void*)); mSingle = ptr; mCount = 1; mBufferUsed = true; mOwnsMemory = true; } else { PX_ASSERT(!mBufferUsed); mList[index] = mList[--mCount]; // remove before adjusting memory if(!mOwnsMemory) // don't own the memory, must alloc realloc(0, Ps::nextPowerOfTwo(PxU32(mCount)-1), sm); // if currently a power of 2, don't jump to the next one else if(Ps::isPowerOfTwo(mCount)) // own the memory, and implicit capacity requires that we downsize realloc(PxU32(mCount)*2, PxU32(mCount), sm); // ... from the next power of 2, which was the old implicit capacity PX_ASSERT(mOwnsMemory); } }
void PtrTable::add(void* ptr, PtrTableStorageManager& sm) { if(mCount == 0) // 0 -> 1, easy case { PX_ASSERT(mOwnsMemory); PX_ASSERT(mList == NULL); PX_ASSERT(!mBufferUsed); mSingle = ptr; mCount = 1; mBufferUsed = true; return; } if(mCount == 1) // 1 -> 2, easy case { PX_ASSERT(mOwnsMemory); PX_ASSERT(mBufferUsed); void* single = mSingle; mList = sm.allocate(2*sizeof(void*)); mList[0] = single; mBufferUsed = false; mOwnsMemory = true; } else { PX_ASSERT(!mBufferUsed); if(!mOwnsMemory) // don't own the memory, must always alloc realloc(0, Ps::nextPowerOfTwo(mCount), sm); // we're guaranteed nextPowerOfTwo(x) > x else if(Ps::isPowerOfTwo(mCount)) // count is at implicit capacity, so realloc realloc(mCount, PxU32(mCount)*2, sm); // ... to next higher power of 2 PX_ASSERT(mOwnsMemory); } mList[mCount++] = ptr; }