RavEngine
Loading...
Searching...
No Matches
PxArray.h
1// Redistribution and use in source and binary forms, with or without
2// modification, are permitted provided that the following conditions
3// are met:
4// * Redistributions of source code must retain the above copyright
5// notice, this list of conditions and the following disclaimer.
6// * Redistributions in binary form must reproduce the above copyright
7// notice, this list of conditions and the following disclaimer in the
8// documentation and/or other materials provided with the distribution.
9// * Neither the name of NVIDIA CORPORATION nor the names of its
10// contributors may be used to endorse or promote products derived
11// from this software without specific prior written permission.
12//
13// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ''AS IS'' AND ANY
14// EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
16// PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR
17// CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
18// EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
19// PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
20// PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
21// OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
22// (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
23// OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24//
25// Copyright (c) 2008-2022 NVIDIA Corporation. All rights reserved.
26// Copyright (c) 2004-2008 AGEIA Technologies, Inc. All rights reserved.
27// Copyright (c) 2001-2004 NovodeX AG. All rights reserved.
28
29#ifndef PX_ARRAY_H
30#define PX_ARRAY_H
31
32#include "foundation/PxAssert.h"
33#include "foundation/PxMathIntrinsics.h"
34#include "foundation/PxAllocator.h"
35#include "foundation/PxBasicTemplates.h"
36#include "foundation/PxMemory.h"
37
38namespace physx
39{
40
51template <class T, class Alloc = typename PxAllocatorTraits<T>::Type>
52class PxArray : protected Alloc
53{
54 public:
55 typedef T* Iterator;
56 typedef const T* ConstIterator;
57
58 explicit PxArray(const PxEMPTY v) : Alloc(v)
59 {
60 if(mData)
61 mCapacity |= PX_SIGN_BITMASK;
62 }
63
67 PX_INLINE explicit PxArray(const Alloc& alloc = Alloc()) : Alloc(alloc), mData(0), mSize(0), mCapacity(0)
68 {
69 }
70
74 PX_INLINE explicit PxArray(uint32_t size, const T& a = T(), const Alloc& alloc = Alloc())
75 : Alloc(alloc), mData(0), mSize(0), mCapacity(0)
76 {
77 resize(size, a);
78 }
79
83 template <class A>
84 PX_INLINE explicit PxArray(const PxArray<T, A>& other, const Alloc& alloc = Alloc())
85 : Alloc(alloc)
86 {
87 copy(other);
88 }
89
90 // This is necessary else the basic default copy constructor is used in the case of both arrays being of the same
91 // template instance
92 // The C++ standard clearly states that a template constructor is never a copy constructor [2]. In other words,
93 // the presence of a template constructor does not suppress the implicit declaration of the copy constructor.
94 // Also never make a copy constructor explicit, or copy-initialization* will no longer work. This is because
95 // 'binding an rvalue to a const reference requires an accessible copy constructor' (http://gcc.gnu.org/bugs/)
96 // *http://stackoverflow.com/questions/1051379/is-there-a-difference-in-c-between-copy-initialization-and-assignment-initializ
97 PX_INLINE PxArray(const PxArray& other, const Alloc& alloc = Alloc()) : Alloc(alloc)
98 {
99 copy(other);
100 }
101
105 PX_INLINE explicit PxArray(const T* first, const T* last, const Alloc& alloc = Alloc())
106 : Alloc(alloc), mSize(last < first ? 0 : uint32_t(last - first)), mCapacity(mSize)
107 {
108 mData = allocate(mSize);
109 copy(mData, mData + mSize, first);
110 }
111
116 {
117 destroy(mData, mData + mSize);
118
119 if(capacity() && !isInUserMemory())
120 deallocate(mData);
121 }
122
126 template <class A>
128 {
129 if(&rhs == this)
130 return *this;
131
132 clear();
133 reserve(rhs.mSize);
134 copy(mData, mData + rhs.mSize, rhs.mData);
135
136 mSize = rhs.mSize;
137 return *this;
138 }
139
140 PX_INLINE PxArray& operator=(const PxArray& t) // Needs to be declared, see comment at copy-constructor
141 {
142 return operator=<Alloc>(t);
143 }
144
152 PX_FORCE_INLINE const T& operator[](uint32_t i) const
153 {
154 PX_ASSERT(i < mSize);
155 return mData[i];
156 }
157
166 {
167 PX_ASSERT(i < mSize);
168 return mData[i];
169 }
170
176 PX_FORCE_INLINE ConstIterator begin() const
177 {
178 return mData;
179 }
180
181 PX_FORCE_INLINE Iterator begin()
182 {
183 return mData;
184 }
185
192 PX_FORCE_INLINE ConstIterator end() const
193 {
194 return mData + mSize;
195 }
196
197 PX_FORCE_INLINE Iterator end()
198 {
199 return mData + mSize;
200 }
201
207 PX_FORCE_INLINE const T& front() const
208 {
209 PX_ASSERT(mSize);
210 return mData[0];
211 }
212
214 {
215 PX_ASSERT(mSize);
216 return mData[0];
217 }
218
224 PX_FORCE_INLINE const T& back() const
225 {
226 PX_ASSERT(mSize);
227 return mData[mSize - 1];
228 }
229
231 {
232 PX_ASSERT(mSize);
233 return mData[mSize - 1];
234 }
235
242 PX_FORCE_INLINE uint32_t size() const
243 {
244 return mSize;
245 }
246
251 {
252 destroy(mData, mData + mSize);
253 mSize = 0;
254 }
255
262 {
263 return mSize == 0;
264 }
265
272 PX_INLINE Iterator find(const T& a)
273 {
274 uint32_t index;
275 for(index = 0; index < mSize && mData[index] != a; index++)
276 ;
277 return mData + index;
278 }
279
280 PX_INLINE ConstIterator find(const T& a) const
281 {
282 uint32_t index;
283 for(index = 0; index < mSize && mData[index] != a; index++)
284 ;
285 return mData + index;
286 }
287
289
295
297 {
298 if(capacity() <= mSize)
299 return growAndPushBack(a);
300
301 PX_PLACEMENT_NEW(reinterpret_cast<void*>(mData + mSize), T)(a);
302
303 return mData[mSize++];
304 }
305
307
312 {
313 PX_ASSERT(mSize);
314 T t = mData[mSize - 1];
315
316 mData[--mSize].~T();
317
318 return t;
319 }
320
322
327 {
328 if(capacity() <= mSize)
329 grow(capacityIncrement());
330
331 T* ptr = mData + mSize++;
332 PX_PLACEMENT_NEW(ptr, T); // not 'T()' because PODs should not get default-initialized.
333 return *ptr;
334 }
335
337
345 PX_INLINE void replaceWithLast(uint32_t i)
346 {
347 PX_ASSERT(i < mSize);
348 mData[i] = mData[--mSize];
349
350 mData[mSize].~T();
351 }
352
353 PX_INLINE void replaceWithLast(Iterator i)
354 {
355 replaceWithLast(static_cast<uint32_t>(i - mData));
356 }
357
359
367
369 {
370 uint32_t index = 0;
371 while(index < mSize && mData[index] != a)
372 ++index;
373 if(index == mSize)
374 return false;
375 replaceWithLast(index);
376 return true;
377 }
378
380
388 PX_INLINE void remove(uint32_t i)
389 {
390 PX_ASSERT(i < mSize);
391
392 T* it = mData + i;
393 it->~T();
394 while (++i < mSize)
395 {
396 PX_PLACEMENT_NEW(it, T(mData[i]));
397 ++it;
398 it->~T();
399 }
400 --mSize;
401 }
402
404
413 PX_INLINE void removeRange(uint32_t begin, uint32_t count)
414 {
415 PX_ASSERT(begin < mSize);
416 PX_ASSERT((begin + count) <= mSize);
417
418 for(uint32_t i = 0; i < count; i++)
419 mData[begin + i].~T(); // call the destructor on the ones being removed first.
420
421 T* dest = &mData[begin]; // location we are copying the tail end objects to
422 T* src = &mData[begin + count]; // start of tail objects
423 uint32_t move_count = mSize - (begin + count); // compute remainder that needs to be copied down
424
425 for(uint32_t i = 0; i < move_count; i++)
426 {
427 PX_PLACEMENT_NEW(dest, T(*src)); // copy the old one to the new location
428 src->~T(); // call the destructor on the old location
429 dest++;
430 src++;
431 }
432 mSize -= count;
433 }
434
436
440 PX_NOINLINE void resize(const uint32_t size, const T& a = T());
441
442 PX_NOINLINE void resizeUninitialized(const uint32_t size);
443
445
451 {
452 recreate(mSize);
453 }
454
456
461 {
462 resize(0);
463 shrink();
464 }
465
467
472 {
473 const PxU32 c = capacity();
474 const PxU32 s = size();
475 if(s>=c/2)
476 clear();
477 else
478 reset();
479 }
480
482
486 PX_INLINE void reserve(const uint32_t capacity)
487 {
488 if(capacity > this->capacity())
489 grow(capacity);
490 }
491
493
497 PX_FORCE_INLINE uint32_t capacity() const
498 {
499 return mCapacity & ~PX_SIGN_BITMASK;
500 }
501
503
508 {
509 PX_ASSERT(size <= mCapacity);
510 mSize = size;
511 }
512
514
519 {
520 PxSwap(mData, other.mData);
521 PxSwap(mSize, other.mSize);
522 PxSwap(mCapacity, other.mCapacity);
523 }
524
526
530 PX_INLINE void assign(const T* first, const T* last)
531 {
532 resizeUninitialized(uint32_t(last - first));
533 copy(begin(), end(), first);
534 }
535
536 // We need one bit to mark arrays that have been deserialized from a user-provided memory block.
537 // For alignment & memory saving purpose we store that bit in the rarely used capacity member.
538 PX_FORCE_INLINE uint32_t isInUserMemory() const
539 {
540 return mCapacity & PX_SIGN_BITMASK;
541 }
542
545 {
546 return *this;
547 }
548
549 protected:
550 // constructor for where we don't own the memory
551 PxArray(T* memory, uint32_t size, uint32_t capacity, const Alloc& alloc = Alloc())
552 : Alloc(alloc), mData(memory), mSize(size), mCapacity(capacity | PX_SIGN_BITMASK)
553 {
554 }
555
556 template <class A>
557 PX_NOINLINE void copy(const PxArray<T, A>& other);
558
559 PX_INLINE T* allocate(uint32_t size)
560 {
561 if(size > 0)
562 {
563 T* p = reinterpret_cast<T*>(Alloc::allocate(sizeof(T) * size, __FILE__, __LINE__));
564 PxMarkSerializedMemory(p, sizeof(T) * size);
565 return p;
566 }
567 return 0;
568 }
569
570 PX_INLINE void deallocate(void* mem)
571 {
572 Alloc::deallocate(mem);
573 }
574
575 static PX_INLINE void create(T* first, T* last, const T& a)
576 {
577 for(; first < last; ++first)
578 ::PX_PLACEMENT_NEW(first, T(a));
579 }
580
581 static PX_INLINE void copy(T* first, T* last, const T* src)
582 {
583 if(last <= first)
584 return;
585
586 for(; first < last; ++first, ++src)
587 ::PX_PLACEMENT_NEW(first, T(*src));
588 }
589
590 static PX_INLINE void destroy(T* first, T* last)
591 {
592 for(; first < last; ++first)
593 first->~T();
594 }
595
601
608 PX_INLINE void grow(uint32_t capacity)
609 {
610 PX_ASSERT(this->capacity() < capacity);
612 }
613
621
622 // The idea here is to prevent accidental bugs with pushBack or insert. Unfortunately
623 // it interacts badly with InlineArrays with smaller inline allocations.
624 // TODO(dsequeira): policy template arg, this is exactly what they're for.
625 PX_INLINE uint32_t capacityIncrement() const
626 {
627 const uint32_t capacity = this->capacity();
628 return capacity == 0 ? 1 : capacity * 2;
629 }
630
631 T* mData;
632 uint32_t mSize;
633 uint32_t mCapacity;
634};
635
636template <class T, class Alloc>
637PX_NOINLINE void PxArray<T, Alloc>::resize(const uint32_t size, const T& a)
638{
639 reserve(size);
640 create(mData + mSize, mData + size, a);
641 destroy(mData + size, mData + mSize);
642 mSize = size;
643}
644
645template <class T, class Alloc>
646template <class A>
648{
649 if(!other.empty())
650 {
651 mData = allocate(mSize = mCapacity = other.size());
652 copy(mData, mData + mSize, other.begin());
653 }
654 else
655 {
656 mData = NULL;
657 mSize = 0;
658 mCapacity = 0;
659 }
660
661 // mData = allocate(other.mSize);
662 // mSize = other.mSize;
663 // mCapacity = other.mSize;
664 // copy(mData, mData + mSize, other.mData);
665}
666
667template <class T, class Alloc>
668PX_NOINLINE void PxArray<T, Alloc>::resizeUninitialized(const uint32_t size)
669{
670 reserve(size);
671 mSize = size;
672}
673
674template <class T, class Alloc>
676{
677 uint32_t capacity = capacityIncrement();
678
679 T* newData = allocate(capacity);
680 PX_ASSERT((!capacity) || (newData && (newData != mData)));
681 copy(newData, newData + mSize, mData);
682
683 // inserting element before destroying old array
684 // avoids referencing destroyed object when duplicating array element.
685 PX_PLACEMENT_NEW(reinterpret_cast<void*>(newData + mSize), T)(a);
686
687 destroy(mData, mData + mSize);
688 if(!isInUserMemory())
689 deallocate(mData);
690
691 mData = newData;
692 mCapacity = capacity;
693
694 return mData[mSize++];
695}
696
697template <class T, class Alloc>
699{
700 T* newData = allocate(capacity);
701 PX_ASSERT((!capacity) || (newData && (newData != mData)));
702
703 copy(newData, newData + mSize, mData);
704 destroy(mData, mData + mSize);
705 if(!isInUserMemory())
706 deallocate(mData);
707
708 mData = newData;
709 mCapacity = capacity;
710}
711
712template <class T, class Alloc>
714{
715 x.swap(y);
716}
717
718} // namespace physx
719
720#endif
721
Definition PxArray.h:53
PX_INLINE PxArray(uint32_t size, const T &a=T(), const Alloc &alloc=Alloc())
Definition PxArray.h:74
PX_INLINE void shrink()
Definition PxArray.h:450
PX_INLINE Iterator find(const T &a)
Definition PxArray.h:272
PX_INLINE PxArray(const PxArray< T, A > &other, const Alloc &alloc=Alloc())
Definition PxArray.h:84
PX_NOINLINE T & growAndPushBack(const T &a)
Definition PxArray.h:675
PX_INLINE void assign(const T *first, const T *last)
Definition PxArray.h:530
PX_INLINE Alloc & getAllocator()
return reference to allocator
Definition PxArray.h:544
PX_FORCE_INLINE ConstIterator end() const
Definition PxArray.h:192
PX_NOINLINE void resize(const uint32_t size, const T &a=T())
Definition PxArray.h:637
PX_FORCE_INLINE uint32_t size() const
Definition PxArray.h:242
PX_FORCE_INLINE void forceSize_Unsafe(uint32_t size)
Definition PxArray.h:507
PX_FORCE_INLINE const T & front() const
Definition PxArray.h:207
PX_INLINE void reset()
Definition PxArray.h:460
PX_INLINE void clear()
Definition PxArray.h:250
PX_INLINE void removeRange(uint32_t begin, uint32_t count)
Definition PxArray.h:413
PX_NOINLINE void recreate(uint32_t capacity)
Definition PxArray.h:698
PX_INLINE void swap(PxArray< T, Alloc > &other)
Definition PxArray.h:518
PX_FORCE_INLINE const T & operator[](uint32_t i) const
Definition PxArray.h:152
PX_FORCE_INLINE ConstIterator begin() const
Definition PxArray.h:176
PX_FORCE_INLINE bool empty() const
Definition PxArray.h:261
PX_FORCE_INLINE T & operator[](uint32_t i)
Definition PxArray.h:165
PX_FORCE_INLINE uint32_t capacity() const
Definition PxArray.h:497
PX_FORCE_INLINE T & pushBack(const T &a)
Definition PxArray.h:296
PX_INLINE PxArray & operator=(const PxArray< T, A > &rhs)
Definition PxArray.h:127
PX_INLINE void reserve(const uint32_t capacity)
Definition PxArray.h:486
PX_INLINE void replaceWithLast(uint32_t i)
Definition PxArray.h:345
PX_INLINE PxArray(const T *first, const T *last, const Alloc &alloc=Alloc())
Definition PxArray.h:105
PX_INLINE ~PxArray()
Definition PxArray.h:115
PX_INLINE PxArray(const Alloc &alloc=Alloc())
Definition PxArray.h:67
PX_INLINE T popBack()
Definition PxArray.h:311
PX_INLINE T & insert()
Definition PxArray.h:326
PX_INLINE void resetOrClear()
Definition PxArray.h:471
PX_INLINE void grow(uint32_t capacity)
Definition PxArray.h:608
PX_INLINE void remove(uint32_t i)
Definition PxArray.h:388
PX_INLINE bool findAndReplaceWithLast(const T &a)
Definition PxArray.h:368
PX_FORCE_INLINE const T & back() const
Definition PxArray.h:224
#define PX_NOINLINE
Definition PxPreprocessor.h:346
#define PX_FORCE_INLINE
Definition PxPreprocessor.h:335
#define PX_INLINE
Definition PxPreprocessor.h:320
Sorts an array of objects in ascending order, assuming that the predicate implements the < operator:
Definition PxBoxController.h:39
PX_INLINE void PxMarkSerializedMemory(void *ptr, PxU32 byteSize)
Definition PxMemory.h:111
PxEMPTY
Definition Px.h:87