41 #ifndef OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED 42 #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> 190 template <
typename ValueT,
size_t Log2PageSize = 10UL>
195 typedef std::deque<Page*> PageTableT;
201 PagedArray() : mPageTable(), mSize(), mCapacity(0), mGrowthMutex() { mSize = 0; }
228 const size_t index = mSize.fetch_and_increment();
229 if (index >= mCapacity) this->grow(index);
230 (*mPageTable[index >> Log2PageSize])[index] = value;
241 const size_t index = mSize.fetch_and_increment();
242 if (index >= mCapacity) {
243 mPageTable.push_back(
new Page() );
244 mCapacity += Page::Size;
246 (*mPageTable[index >> Log2PageSize])[index] = value;
267 return (*mPageTable[mSize >> Log2PageSize])[mSize];
273 void shrink_to_fit();
283 return (*mPageTable[i>>Log2PageSize])[i];
294 return (*mPageTable[i>>Log2PageSize])[i];
300 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
312 if (size > mCapacity) {
315 this->shrink_to_fit();
323 void resize(
size_t size,
const ValueType& v)
330 size_t size()
const {
return mSize; }
352 return sizeof(*this) + mPageTable.size() * Page::memUsage();
371 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
372 for (
size_t i=0, n=mPageTable.size(); i<n; ++i)
delete mPageTable[i];
373 PageTableT().swap(mPageTable);
399 void sort() { tbb::parallel_sort(this->begin(), this->end(), std::less<ValueT>() ); }
402 void invSort() { tbb::parallel_sort(this->begin(), this->end(), std::greater<ValueT>()); }
408 template <
typename Functor>
409 void sort() { tbb::parallel_sort(this->begin(), this->end(), Functor() ); }
419 void print(std::ostream& os = std::cout)
const 421 os <<
"PagedArray:\n" 422 <<
"\tSize: " << this->size() <<
" elements\n" 423 <<
"\tPage table: " << this->pageCount() <<
" pages\n" 424 <<
"\tPage size: " << this->pageSize() <<
" elements\n" 425 <<
"\tCapacity: " << this->capacity() <<
" elements\n" 426 <<
"\tFootrpint: " << this->memUsage() <<
" bytes\n";
439 void grow(
size_t index)
441 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
442 while(index >= mCapacity) {
443 mPageTable.push_back(
new Page() );
444 mCapacity += Page::Size;
448 void add_full(
Page*& page,
size_t size);
450 void add_partially_full(
Page*& page,
size_t size);
452 void add(
Page*& page,
size_t size) {
453 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
454 if (size == Page::Size) {
455 this->add_full(page, size);
457 this->add_partially_full(page, size);
460 PageTableT mPageTable;
461 tbb::atomic<size_t> mSize;
463 tbb::spin_mutex mGrowthMutex;
468 template <
typename ValueT,
size_t Log2PageSize>
471 if (mPageTable.size() > (mSize >> Log2PageSize) + 1) {
472 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
473 const size_t pageCount = (mSize >> Log2PageSize) + 1;
474 if (mPageTable.size() > pageCount) {
475 delete mPageTable.back();
476 mPageTable.pop_back();
477 mCapacity -= Page::Size;
482 template <
typename ValueT,
size_t Log2PageSize>
486 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
489 const size_t size = mSize & Page::Mask;
491 page = mPageTable.back();
492 mPageTable.pop_back();
496 mPageTable.insert(mPageTable.end(), other.mPageTable.begin(), other.mPageTable.end());
497 mSize += other.mSize;
498 mCapacity = Page::Size*mPageTable.size();
501 PageTableT().swap(other.mPageTable);
503 if (page) this->add_partially_full(page, size);
507 template <
typename ValueT,
size_t Log2PageSize>
510 assert(size == Page::Size);
511 if (mSize & Page::Mask) {
512 Page*& tmp = mPageTable.back();
513 std::swap(tmp, page);
515 mPageTable.push_back( page );
516 mCapacity += Page::Size;
521 template <
typename ValueT,
size_t Log2PageSize>
524 assert(size > 0 && size < Page::Size);
525 if (
size_t m = mSize & Page::Mask) {
526 ValueT *s = page->
data(), *t = mPageTable.back()->data() + m;
527 for (
size_t i=
std::min(mSize+size, mCapacity)-mSize; i; --i) *t++ = *s++;
528 if (mSize+size > mCapacity) {
529 mPageTable.push_back(
new Page() );
530 t = mPageTable.back()->data();
531 for (
size_t i=mSize+size-mCapacity; i; --i) *t++ = *s++;
532 mCapacity += Page::Size;
535 mPageTable.push_back( page );
536 mCapacity += Page::Size;
545 template <
typename ValueT,
size_t Log2PageSize>
563 (*mPage)[mSize++] = v;
564 if (mSize == Page::Size) this->flush();
572 mParent->add(mPage, mSize);
573 if (mPage == NULL) mPage =
new Page();
577 PagedArrayType&
parent()
const {
return *mParent; }
579 size_t size()
const {
return mSize; }
591 template <
typename ValueT,
size_t Log2PageSize>
593 ConstIterator :
public std::iterator<std::random_access_iterator_tag, ValueT>
596 typedef std::iterator<std::random_access_iterator_tag, ValueT>
BaseT;
604 mParent=other.mParent;
614 const ValueT&
operator*()
const {
return (*mParent)[mPos]; }
616 const ValueT&
operator[](
const difference_type& pos)
const {
return (*mParent)[mPos+pos]; }
631 bool isValid()
const {
return mParent != NULL && mPos < mParent->size(); }
632 size_t pos()
const {
return mPos; }
641 template <
typename ValueT,
size_t Log2PageSize>
643 Iterator :
public std::iterator<std::random_access_iterator_tag, ValueT>
646 typedef std::iterator<std::random_access_iterator_tag, ValueT>
BaseT;
654 mParent=other.mParent;
666 ValueT&
operator[](
const difference_type& pos)
const {
return (*mParent)[mPos+pos]; }
681 bool isValid()
const {
return mParent != NULL && mPos < mParent->size(); }
682 size_t pos()
const {
return mPos; }
691 template <
typename ValueT,
size_t Log2PageSize>
696 static const size_t Size = 1UL << Log2PageSize;
697 static const size_t Mask = Size - 1UL;
698 static size_t memUsage() {
return sizeof(ValueT)*Size; }
699 Page() : mData(new ValueT[Size]) {}
701 ValueT&
operator[](
const size_t i) {
return mData[i & Mask]; }
702 const ValueT&
operator[](
const size_t i)
const {
return mData[i & Mask]; }
703 void fill(
const ValueT& v) { ValueT* p = mData;
for (
size_t i=Size; i; --i) *p++ = v; }
704 ValueT*
data() {
return mData; }
714 template <
typename ValueT,
size_t Log2PageSize>
718 tbb::parallel_for(tbb::blocked_range<size_t>(0, d->pageCount()), *
this);
721 for (
size_t i=r.begin(); i!=r.end(); ++i) d->mPageTable[i]->fill(v);
731 #endif // OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED Iterator operator++(int)
Definition: PagedArray.h:661
void clear()
Removes all elements from the array and delete all pages.
Definition: PagedArray.h:369
Definition: PagedArray.h:642
ConstIterator operator--(int)
Definition: PagedArray.h:612
const ValueT & operator[](const size_t i) const
Definition: PagedArray.h:702
const ValueType & operator[](size_t i) const
Return a const-reference to the value at the specified offset.
Definition: PagedArray.h:291
ConstIterator cbegin() const
Return a const iterator pointing to the first element.
Definition: PagedArray.h:389
Iterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:668
void resize(size_t size)
Resize this array to the specified size.
Definition: PagedArray.h:309
Iterator(const Iterator &other)
Definition: PagedArray.h:651
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:364
static size_t log2PageSize()
Return log2 of the number of elements per memory page.
Definition: PagedArray.h:347
difference_type operator-(const Iterator &other) const
Definition: PagedArray.h:672
ConstIterator & operator++()
Definition: PagedArray.h:608
const ValueT & operator*() const
Definition: PagedArray.h:614
size_t pageCount() const
Return the number of allocated memory pages.
Definition: PagedArray.h:341
void resize(size_t size, const ValueType &v)
Resize this array to the specified size and set all elements to the specified value.
Definition: PagedArray.h:323
ConstIterator operator++(int)
Definition: PagedArray.h:611
Fill(PagedArray *_d, const ValueT &_v)
Definition: PagedArray.h:717
ValueT ValueType
Definition: PagedArray.h:198
void operator()(const tbb::blocked_range< size_t > &r) const
Definition: PagedArray.h:720
ValueBuffer(const ValueBuffer &other)
Definition: PagedArray.h:555
const ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:616
size_t size() const
Return the current number of elements cached in this buffer.
Definition: PagedArray.h:579
ValueType & operator[](size_t i)
Return a reference to the value at the specified offset.
Definition: PagedArray.h:280
bool isValid() const
Definition: PagedArray.h:631
BaseT::difference_type difference_type
Definition: PagedArray.h:647
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Matrix multiplication.
Definition: Mat3.h:658
ConstIterator & operator--()
Definition: PagedArray.h:609
Iterator & operator++()
Definition: PagedArray.h:658
Iterator operator-(const difference_type &pos) const
Definition: PagedArray.h:671
Iterator & operator--()
Definition: PagedArray.h:659
size_t capacity() const
Return the maximum number of elements that this array can contain without allocating more memory page...
Definition: PagedArray.h:334
ValueType pop_back()
Returns the last element, decrements the size by one.
Definition: PagedArray.h:263
bool isValid() const
Definition: PagedArray.h:681
difference_type operator-(const ConstIterator &other) const
Definition: PagedArray.h:622
Iterator operator+(const difference_type &pos) const
Definition: PagedArray.h:670
Iterator begin()
Return a non-const iterator pointing to the first element.
Definition: PagedArray.h:379
ConstIterator operator-(const difference_type &pos) const
Definition: PagedArray.h:621
BaseT::difference_type difference_type
Definition: PagedArray.h:597
Iterator(PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:650
Iterator end()
Return a non-const iterator pointing to the past-the-last element.
Definition: PagedArray.h:386
ValueT & operator*() const
Definition: PagedArray.h:664
void push_back(const ValueT &v)
Add a value to the buffer and increment the size.
Definition: PagedArray.h:562
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:158
#define OPENVDB_VERSION_NAME
Definition: version.h:43
size_t size() const
Return the number of elements in this array.
Definition: PagedArray.h:330
const ValueT & v
Definition: PagedArray.h:724
bool operator<=(const ConstIterator &other) const
Definition: PagedArray.h:627
PagedArray * d
Definition: PagedArray.h:723
ValueT * data()
Definition: PagedArray.h:704
ConstIterator()
Definition: PagedArray.h:599
void invSort()
Parallel sort of all the elements in descending order.
Definition: PagedArray.h:402
size_t memUsage() const
Return the memory footprint of this array in bytes.
Definition: PagedArray.h:350
Definition: Exceptions.h:39
bool operator<=(const Iterator &other) const
Definition: PagedArray.h:677
size_t push_back(const ValueType &value)
Thread safe insertion, adds a new element at the end and increases the container size by one...
Definition: PagedArray.h:226
const ValueT * operator->() const
Definition: PagedArray.h:615
Definition: PagedArray.h:715
PagedArrayType & parent() const
Return a reference to the parent PagedArray.
Definition: PagedArray.h:577
ValueT * operator->() const
Definition: PagedArray.h:665
ConstIterator(const PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:600
ConstIterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:619
ConstIterator operator+(const difference_type &pos) const
Definition: PagedArray.h:620
Iterator()
Definition: PagedArray.h:649
ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:666
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:596
~Page()
Definition: PagedArray.h:700
void fill(const ValueType &v)
Set all elements to the specified value.
Definition: PagedArray.h:298
ConstIterator & operator=(const ConstIterator &other)
Definition: PagedArray.h:602
ValueT & operator[](const size_t i)
Definition: PagedArray.h:701
void sort()
Parallel sort of all the elements based on a custom functor with the api:
Definition: PagedArray.h:409
PagedArray< ValueT, Log2PageSize > PagedArrayType
Definition: PagedArray.h:550
bool operator>=(const Iterator &other) const
Definition: PagedArray.h:676
bool operator!=(const Iterator &other) const
Definition: PagedArray.h:675
void print(std::ostream &os=std::cout) const
Print information for debugging.
Definition: PagedArray.h:419
Iterator & operator=(const Iterator &other)
Definition: PagedArray.h:652
size_t freeCount() const
Return the number of additional elements that can be added to this array without allocating more memo...
Definition: PagedArray.h:338
Page()
Definition: PagedArray.h:699
PagedArray()
Default constructor.
Definition: PagedArray.h:201
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:646
Definition: PagedArray.h:546
Definition: PagedArray.h:692
ValueT * mData
Definition: PagedArray.h:708
bool operator==(const ConstIterator &other) const
Definition: PagedArray.h:624
Definition: PagedArray.h:592
static size_t pageSize()
Return the number of elements per memory page.
Definition: PagedArray.h:344
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:170
size_t pos() const
Definition: PagedArray.h:632
void fill(const ValueT &v)
Definition: PagedArray.h:703
bool isEmpty() const
Return true if the container contains no elements.
Definition: PagedArray.h:356
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
~ValueBuffer()
Destructor that transfers an buffered values to the parent PagedArray.
Definition: PagedArray.h:557
ValueBuffer(PagedArray &parent)
Constructor from a PageArray.
Definition: PagedArray.h:552
Iterator operator--(int)
Definition: PagedArray.h:662
Concurrent page-based linear data structure with O(1) random access and std-compliant iterators...
Definition: PagedArray.h:191
void flush()
Manually transfer the values in this buffer to the parent PagedArray.
Definition: PagedArray.h:571
~PagedArray()
Destructor removed all allocated pages.
Definition: PagedArray.h:204
static size_t memUsage()
Definition: PagedArray.h:698
Iterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:669
size_t push_back_unsafe(const ValueType &value)
Slightly faster then the thread-safe push_back above.
Definition: PagedArray.h:239
bool operator>=(const ConstIterator &other) const
Definition: PagedArray.h:626
void sort()
Parallel sort of all the elements in ascending order.
Definition: PagedArray.h:399
bool operator!=(const ConstIterator &other) const
Definition: PagedArray.h:625
ConstIterator cend() const
Return a const iterator pointing to the past-the-last element.
Definition: PagedArray.h:396
bool operator==(const Iterator &other) const
Definition: PagedArray.h:674
ConstIterator(const ConstIterator &other)
Definition: PagedArray.h:601
size_t pos() const
Definition: PagedArray.h:682
ConstIterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:618