42 #ifndef OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED 43 #define OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED 49 #include <tbb/atomic.h> 50 #include <tbb/spin_mutex.h> 51 #include <tbb/parallel_for.h> 52 #include <tbb/parallel_sort.h> 185 template<
typename ValueT,
186 size_t Log2PageSize = 10UL,
187 template<
typename ...>
class TableT = std::vector>
193 #if defined(__INTEL_COMPILER) && __INTEL_COMPILER < 1700 195 using PageTableT = TableT<Page*, std::allocator<Page*>>;
197 using PageTableT = TableT<Page*>;
238 const size_t index = mSize.fetch_and_increment();
239 if (index >= mCapacity) this->grow(index);
240 (*mPageTable[index >> Log2PageSize])[index] = value;
253 const size_t index = mSize.fetch_and_increment();
254 if (index >= mCapacity) {
255 mPageTable.push_back(
new Page() );
256 mCapacity += Page::Size;
258 (*mPageTable[index >> Log2PageSize])[index] = value;
286 return (*mPageTable[mSize >> Log2PageSize])[mSize];
293 void shrink_to_fit();
305 return (*mPageTable[i>>Log2PageSize])[
i];
318 return (*mPageTable[i>>Log2PageSize])[
i];
328 auto op = [&](
const tbb::blocked_range<size_t>& r){
329 for(
size_t i=r.begin();
i!=r.end(); ++
i) mPageTable[
i]->fill(v);
331 tbb::parallel_for(tbb::blocked_range<size_t>(0, this->pageCount()), op);
341 bool copy(ValueType *p,
size_t count)
const 343 size_t last_page = count >> Log2PageSize;
344 if (last_page >= this->pageCount())
return false;
345 auto op = [&](
const tbb::blocked_range<size_t>& r){
346 for (
size_t i=r.begin();
i!=r.end(); ++
i) {
347 mPageTable[
i]->copy(p+
i*Page::Size, Page::Size);
350 if (
size_t m = count & Page::Mask) {
351 tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page, 32), op);
352 mPageTable[last_page]->copy(p+last_page*Page::Size, m);
354 tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page+1, 32), op);
358 void copy(ValueType *p)
const { this->
copy(p, mSize); }
377 if (size > mCapacity) {
380 this->shrink_to_fit();
406 size_t size()
const {
return mSize; }
428 return sizeof(*this) + mPageTable.size() * Page::memUsage();
447 for (
size_t i=0, n=mPageTable.size();
i<n; ++
i)
delete mPageTable[
i];
448 PageTableT().swap(mPageTable);
480 void sort() { tbb::parallel_sort(this->begin(), this->end(), std::less<ValueT>() ); }
483 void invSort() { tbb::parallel_sort(this->begin(), this->end(), std::greater<ValueT>()); }
486 template <
typename Functor>
491 void sort(Functor func) { tbb::parallel_sort(this->begin(), this->end(), func ); }
504 void print(std::ostream& os = std::cout)
const 506 os <<
"PagedArray:\n" 507 <<
"\tSize: " << this->
size() <<
" elements\n" 508 <<
"\tPage table: " << this->pageCount() <<
" pages\n" 509 <<
"\tPage size: " << this->pageSize() <<
" elements\n" 510 <<
"\tCapacity: " << this->capacity() <<
" elements\n" 511 <<
"\tFootprint: " << this->memUsage() <<
" bytes\n";
518 void grow(
size_t index)
520 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
521 while(index >= mCapacity) {
522 mPageTable.push_back(
new Page() );
523 mCapacity += Page::Size;
527 void add_full(
Page*& page,
size_t size);
529 void add_partially_full(
Page*& page,
size_t size);
531 void add(
Page*& page,
size_t size) {
532 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
533 if (size == Page::Size) {
534 this->add_full(page, size);
536 this->add_partially_full(page, size);
539 PageTableT mPageTable;
540 tbb::atomic<size_t> mSize{0};
541 size_t mCapacity = 0;
542 tbb::spin_mutex mGrowthMutex;
547 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
550 if (mPageTable.size() > (mSize >> Log2PageSize) + 1) {
551 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
552 const size_t pageCount = (mSize >> Log2PageSize) + 1;
553 if (mPageTable.size() > pageCount) {
554 delete mPageTable.back();
555 mPageTable.pop_back();
556 mCapacity -= Page::Size;
561 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
564 if (&other !=
this && !other.
isEmpty()) {
565 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
567 Page* page =
nullptr;
568 const size_t size = mSize & Page::Mask;
570 page = mPageTable.back();
571 mPageTable.pop_back();
575 mPageTable.insert(mPageTable.end(), other.mPageTable.begin(), other.mPageTable.end());
576 mSize += other.mSize;
577 mCapacity = Page::Size*mPageTable.size();
580 PageTableT().swap(other.mPageTable);
582 if (page) this->add_partially_full(page, size);
586 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
589 assert(size == Page::Size);
590 if (mSize & Page::Mask) {
591 Page*& tmp = mPageTable.back();
592 std::swap(tmp, page);
594 mPageTable.push_back(page);
595 mCapacity += Page::Size;
600 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
603 assert(size > 0 && size < Page::Size);
604 if (
size_t m = mSize & Page::Mask) {
605 ValueT *s = page->
data(), *t = mPageTable.back()->data() + m;
606 for (
size_t i=
std::min(mSize+size, mCapacity)-mSize;
i; --
i) *t++ = *s++;
607 if (mSize+size > mCapacity) {
608 mPageTable.push_back(
new Page() );
609 t = mPageTable.back()->data();
610 for (
size_t i=mSize+size-mCapacity;
i; --
i) *t++ = *s++;
611 mCapacity += Page::Size;
614 mPageTable.push_back( page );
615 mCapacity += Page::Size;
624 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
645 (*mPage)[mSize++] = v;
646 if (mSize == Page::Size) this->flush();
654 mParent->add(mPage, mSize);
655 if (mPage ==
nullptr) mPage =
new Page();
659 PagedArrayType&
parent()
const {
return *mParent; }
661 size_t size()
const {
return mSize; }
672 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
674 ConstIterator :
public std::iterator<std::random_access_iterator_tag, ValueT>
677 typedef std::iterator<std::random_access_iterator_tag, ValueT>
BaseT;
685 mParent=other.mParent;
695 const ValueT&
operator*()
const {
return (*mParent)[mPos]; }
697 const ValueT&
operator[](
const difference_type& pos)
const {
return (*mParent)[mPos+pos]; }
712 bool isValid()
const {
return mParent !=
nullptr && mPos < mParent->size(); }
713 size_t pos()
const {
return mPos; }
723 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
725 Iterator :
public std::iterator<std::random_access_iterator_tag, ValueT>
728 typedef std::iterator<std::random_access_iterator_tag, ValueT>
BaseT;
736 mParent=other.mParent;
748 ValueT&
operator[](
const difference_type& pos)
const {
return (*mParent)[mPos+pos]; }
763 bool isValid()
const {
return mParent !=
nullptr && mPos < mParent->size(); }
764 size_t pos()
const {
return mPos; }
773 template <
typename ValueT,
size_t Log2PageSize,
template<
typename ...>
class TableT>
778 static const size_t Size = 1UL << Log2PageSize;
779 static const size_t Mask = Size - 1UL;
780 static size_t memUsage() {
return sizeof(ValueT)*Size; }
782 Page() : mData(reinterpret_cast<ValueT*>(new char[sizeof(ValueT)*Size])) {}
785 Page& operator=(
const Page&) =
delete;
787 const ValueT&
operator[](
const size_t i)
const {
return mData[i & Mask]; }
790 for (
size_t i=Size;
i; --
i) *dst++ = v;
792 ValueT*
data() {
return mData; }
795 void copy(ValueType *dst,
size_t n)
const {
796 const ValueT* src = mData;
797 for (
size_t i=n;
i; --
i) *dst++ = *src++;
809 #endif // OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED ~PagedArray()
Destructor removed all allocated pages.
Definition: PagedArray.h:207
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:218
ConstIterator & operator=(const ConstIterator &other)
Definition: PagedArray.h:683
size_t pos() const
Definition: PagedArray.h:713
Definition: PagedArray.h:774
bool isValid() const
Definition: PagedArray.h:763
size_t push_back(const ValueType &value)
Thread safe insertion, adds a new element at the end and increases the container size by one and retu...
Definition: PagedArray.h:236
bool copy(ValueType *p, size_t count) const
Copy the first count values in this PageArray into a raw c-style array, assuming it to be at least co...
Definition: PagedArray.h:341
void sort()
Parallel sort of all the elements in ascending order.
Definition: PagedArray.h:480
Iterator begin()
Return a non-const iterator pointing to the first element.
Definition: PagedArray.h:454
ValueT & operator[](const size_t i)
Definition: PagedArray.h:786
void fill(const ValueT &v)
Definition: PagedArray.h:788
ValueBuffer(const ValueBuffer &other)
Definition: PagedArray.h:634
ConstIterator & operator--()
Definition: PagedArray.h:690
const ValueT & operator[](const size_t i) const
Definition: PagedArray.h:787
ConstIterator end() const
Return a const iterator pointing to the past-the-last element.
Definition: PagedArray.h:476
BaseT::difference_type difference_type
Definition: PagedArray.h:678
size_t freeCount() const
Return the number of additional elements that can be added to this array without allocating more memo...
Definition: PagedArray.h:414
tbb::atomic< Index32 > i
Definition: LeafBuffer.h:71
void print(std::ostream &os=std::cout) const
Print information for debugging.
Definition: PagedArray.h:504
Iterator operator--(int)
Definition: PagedArray.h:744
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:677
size_t size() const
Return the current number of elements cached in this buffer.
Definition: PagedArray.h:661
bool operator>=(const ConstIterator &other) const
Definition: PagedArray.h:707
Iterator operator++(int)
Definition: PagedArray.h:743
void push_back(const ValueT &v)
Add a value to the buffer and increment the size.
Definition: PagedArray.h:644
const ValueType & operator[](size_t i) const
Return a const-reference to the value at the specified offset.
Definition: PagedArray.h:315
bool operator==(const Iterator &other) const
Definition: PagedArray.h:756
size_t push_back_unsafe(const ValueType &value)
Slightly faster than the thread-safe push_back above.
Definition: PagedArray.h:251
ValueT * operator->() const
Definition: PagedArray.h:747
size_t pos() const
Definition: PagedArray.h:764
ValueT & operator*() const
Definition: PagedArray.h:746
Iterator(const Iterator &other)
Definition: PagedArray.h:733
ConstIterator begin() const
Return a const iterator pointing to the first element.
Definition: PagedArray.h:466
ConstIterator(const ConstIterator &other)
Definition: PagedArray.h:682
bool operator==(const ConstIterator &other) const
Definition: PagedArray.h:705
bool operator<=(const ConstIterator &other) const
Definition: PagedArray.h:708
ConstIterator & operator++()
Definition: PagedArray.h:689
PagedArray< ValueT, Log2PageSize, TableT > PagedArrayType
Definition: PagedArray.h:629
ConstIterator operator--(int)
Definition: PagedArray.h:693
size_t size() const
Return the number of elements in this array.
Definition: PagedArray.h:406
void copy(ValueType *p) const
Definition: PagedArray.h:358
const ValueT & operator*() const
Definition: PagedArray.h:695
ConstIterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:699
difference_type operator-(const ConstIterator &other) const
Definition: PagedArray.h:703
Iterator & operator=(const Iterator &other)
Definition: PagedArray.h:734
size_t capacity() const
Return the maximum number of elements that this array can contain without allocating more memory page...
Definition: PagedArray.h:410
Definition: PagedArray.h:673
Iterator operator+(const difference_type &pos) const
Definition: PagedArray.h:752
#define OPENVDB_VERSION_NAME
Definition: version.h:43
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:728
OPENVDB_DEPRECATED ValueType pop_back()
Returns the last element, decrements the size by one.
Definition: PagedArray.h:282
Definition: PagedArray.h:625
ConstIterator()
Definition: PagedArray.h:680
bool isValid() const
Definition: PagedArray.h:712
bool isPartiallyFull() const
Return true if the page table is partially full, i.e. the last non-empty page contains less than page...
Definition: PagedArray.h:440
ConstIterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:700
void copy(ValueType *dst, size_t n) const
Definition: PagedArray.h:795
Iterator()
Definition: PagedArray.h:731
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:206
void clear()
Removes all elements from the array and delete all pages.
Definition: PagedArray.h:445
Definition: Exceptions.h:39
ValueType & operator[](size_t i)
Return a reference to the value at the specified offset.
Definition: PagedArray.h:302
ConstIterator(const PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:681
Definition: PagedArray.h:724
Concurrent, page-based, dynamically-sized linear data structure with O(1) random access and STL-compl...
Definition: PagedArray.h:188
~Page()
Definition: PagedArray.h:783
bool operator>=(const Iterator &other) const
Definition: PagedArray.h:758
size_t pageCount() const
Return the number of allocated memory pages.
Definition: PagedArray.h:417
const ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:697
bool operator<=(const Iterator &other) const
Definition: PagedArray.h:759
ValueT ValueType
Definition: PagedArray.h:201
void fill(const ValueType &v)
Set all elements in the page table to the specified value.
Definition: PagedArray.h:326
Iterator(PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:732
void resize(size_t size)
Resize this array to the specified size.
Definition: PagedArray.h:374
static size_t log2PageSize()
Return log2 of the number of elements per memory page.
Definition: PagedArray.h:423
ConstIterator operator++(int)
Definition: PagedArray.h:692
PagedArrayType & parent() const
Return a reference to the parent PagedArray.
Definition: PagedArray.h:659
Iterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:750
ConstIterator operator-(const difference_type &pos) const
Definition: PagedArray.h:702
static size_t pageSize()
Return the number of elements per memory page.
Definition: PagedArray.h:420
ConstIterator operator+(const difference_type &pos) const
Definition: PagedArray.h:701
bool operator!=(const ConstIterator &other) const
Definition: PagedArray.h:706
difference_type operator-(const Iterator &other) const
Definition: PagedArray.h:754
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Matrix multiplication.
Definition: Mat3.h:654
Iterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:751
bool isEmpty() const
Return true if the container contains no elements.
Definition: PagedArray.h:432
~ValueBuffer()
Destructor that transfers an buffered values to the parent PagedArray.
Definition: PagedArray.h:636
ValueBuffer(PagedArray &parent)
Constructor from a PageArray.
Definition: PagedArray.h:631
ValueT * mData
Definition: PagedArray.h:800
void resize(size_t size, const ValueType &v)
Resize this array to the specified size and initialize all values to v.
Definition: PagedArray.h:399
void invSort()
Parallel sort of all the elements in descending order.
Definition: PagedArray.h:483
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
Iterator end()
Return a non-const iterator pointing to the past-the-last element.
Definition: PagedArray.h:461
ValueT * data()
Definition: PagedArray.h:792
size_t memUsage() const
Return the memory footprint of this array in bytes.
Definition: PagedArray.h:426
static size_t memUsage()
Definition: PagedArray.h:780
const ValueT * operator->() const
Definition: PagedArray.h:696
ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:748
void sort(Functor func)
Parallel sort of all the elements based on a custom functor with the api:
Definition: PagedArray.h:491
static constexpr size_t size
The size of a LeafBuffer when LeafBuffer::mOutOfCore is atomic.
Definition: LeafBuffer.h:85
BaseT::difference_type difference_type
Definition: PagedArray.h:729
Page()
Definition: PagedArray.h:782
Iterator & operator++()
Definition: PagedArray.h:740
void flush()
Manually transfers the values in this buffer to the parent PagedArray.
Definition: PagedArray.h:653
Iterator & operator--()
Definition: PagedArray.h:741
bool operator!=(const Iterator &other) const
Definition: PagedArray.h:757
Iterator operator-(const difference_type &pos) const
Definition: PagedArray.h:753