Go to the documentation of this file.
15 #ifndef OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED
16 #define OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED
24 #include <tbb/atomic.h>
25 #include <tbb/spin_mutex.h>
26 #include <tbb/parallel_for.h>
27 #include <tbb/parallel_sort.h>
141 template<
typename ValueT,
size_t Log2PageSize = 10UL>
145 static_assert(Log2PageSize > 1UL,
"Expected Log2PageSize > 1");
149 using PageTableT = std::deque<Page*>;
190 return this->push_back_unsafe(value);
200 const size_t index = mSize.fetch_and_increment();
201 if (index >= mCapacity) {
202 mPageTable.push_back(
new Page() );
203 mCapacity += Page::Size;
205 (*mPageTable[index >> Log2PageSize])[index] = value;
212 void shrink_to_fit();
224 return (*mPageTable[i>>Log2PageSize])[i];
237 return (*mPageTable[i>>Log2PageSize])[i];
247 auto op = [&](
const tbb::blocked_range<size_t>& r){
248 for(
size_t i=r.begin(); i!=r.end(); ++i) mPageTable[i]->fill(v);
250 tbb::parallel_for(tbb::blocked_range<size_t>(0, this->pageCount()), op);
262 size_t last_page = count >> Log2PageSize;
263 if (last_page >= this->pageCount())
return false;
264 auto op = [&](
const tbb::blocked_range<size_t>& r){
265 for (
size_t i=r.begin(); i!=r.end(); ++i) {
266 mPageTable[i]->copy(p+i*Page::Size, Page::Size);
269 if (
size_t m = count & Page::Mask) {
270 tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page, 32), op);
271 mPageTable[last_page]->copy(p+last_page*Page::Size, m);
273 tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page+1, 32), op);
296 if (size > mCapacity) {
299 this->shrink_to_fit();
325 size_t size()
const {
return mSize; }
347 return sizeof(*this) + mPageTable.size() * Page::memUsage();
366 for (
size_t i=0, n=mPageTable.size(); i<n; ++i)
delete mPageTable[i];
367 PageTableT().swap(mPageTable);
383 ConstIterator cbegin()
const {
return ConstIterator(*
this, 0); }
389 ConstIterator cend()
const {
return ConstIterator(*
this, mSize); }
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>()); }
405 template <
typename Functor>
410 void sort(Functor func) { tbb::parallel_sort(this->begin(), this->end(), func ); }
423 void print(std::ostream& os = std::cout)
const
425 os <<
"PagedArray:\n"
426 <<
"\tSize: " << this->size() <<
" elements\n"
427 <<
"\tPage table: " << this->pageCount() <<
" pages\n"
428 <<
"\tPage size: " << this->pageSize() <<
" elements\n"
429 <<
"\tCapacity: " << this->capacity() <<
" elements\n"
430 <<
"\tFootprint: " << this->memUsage() <<
" bytes\n";
437 void grow(
size_t index)
439 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
440 while(index >= mCapacity) {
441 mPageTable.push_back(
new Page() );
442 mCapacity += Page::Size;
446 void add_full(Page*& page,
size_t size);
448 void add_partially_full(Page*& page,
size_t size);
450 void add(Page*& page,
size_t size) {
451 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
452 if (size == Page::Size) {
453 this->add_full(page, size);
455 this->add_partially_full(page, size);
458 PageTableT mPageTable;
459 tbb::atomic<size_t> mSize;
461 tbb::spin_mutex mGrowthMutex;
466 template <
typename ValueT,
size_t Log2PageSize>
469 if (mPageTable.size() > (mSize >> Log2PageSize) + 1) {
470 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
471 const size_t pageCount = (mSize >> Log2PageSize) + 1;
472 if (mPageTable.size() > pageCount) {
473 delete mPageTable.back();
474 mPageTable.pop_back();
475 mCapacity -= Page::Size;
480 template <
typename ValueT,
size_t Log2PageSize>
483 if (&other !=
this && !other.
isEmpty()) {
484 tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
486 Page* page =
nullptr;
487 const size_t size = mSize & Page::Mask;
489 page = mPageTable.back();
490 mPageTable.pop_back();
494 mPageTable.insert(mPageTable.end(), other.mPageTable.begin(), other.mPageTable.end());
495 mSize += other.mSize;
496 mCapacity = Page::Size*mPageTable.size();
499 PageTableT().swap(other.mPageTable);
501 if (page) this->add_partially_full(page, size);
505 template <
typename ValueT,
size_t Log2PageSize>
508 assert(size == Page::Size);
509 if (mSize & Page::Mask) {
510 Page*& tmp = mPageTable.back();
511 std::swap(tmp, page);
513 mPageTable.push_back(page);
514 mCapacity += Page::Size;
519 template <
typename ValueT,
size_t Log2PageSize>
520 void PagedArray<ValueT, Log2PageSize>::add_partially_full(Page*& page,
size_t size)
522 assert(size > 0 && size < Page::Size);
523 if (
size_t m = mSize & Page::Mask) {
524 ValueT *s = page->data(), *t = mPageTable.back()->data() + m;
525 for (
size_t i=
std::min(mSize+size, mCapacity)-mSize; i; --i) *t++ = *s++;
526 if (mSize+size > mCapacity) {
527 mPageTable.push_back(
new Page() );
528 t = mPageTable.back()->data();
529 for (
size_t i=mSize+size-mCapacity; i; --i) *t++ = *s++;
530 mCapacity += Page::Size;
533 mPageTable.push_back( page );
534 mCapacity += Page::Size;
543 template <
typename ValueT,
size_t Log2PageSize>
564 (*mPage)[mSize++] = v;
565 if (mSize == Page::Size) this->flush();
573 mParent->add(mPage, mSize);
574 if (mPage ==
nullptr) mPage =
new Page();
580 size_t size()
const {
return mSize; }
581 static size_t pageSize() {
return 1UL << Log2PageSize; }
592 template <
typename ValueT,
size_t Log2PageSize>
594 ConstIterator :
public std::iterator<std::random_access_iterator_tag, ValueT>
597 using BaseT = std::iterator<std::random_access_iterator_tag, ValueT>;
605 mParent=other.mParent;
615 const ValueT&
operator*()
const {
return (*mParent)[mPos]; }
632 bool isValid()
const {
return mParent !=
nullptr && mPos < mParent->size(); }
633 size_t pos()
const {
return mPos; }
643 template <
typename ValueT,
size_t Log2PageSize>
645 Iterator :
public std::iterator<std::random_access_iterator_tag, ValueT>
648 using BaseT = std::iterator<std::random_access_iterator_tag, ValueT>;
656 mParent=other.mParent;
683 bool isValid()
const {
return mParent !=
nullptr && mPos < mParent->size(); }
684 size_t pos()
const {
return mPos; }
693 template <
typename ValueT,
size_t Log2PageSize>
698 static const size_t Size = 1UL << Log2PageSize;
699 static const size_t Mask = Size - 1UL;
700 static size_t memUsage() {
return sizeof(ValueT)*Size; }
702 Page() : mData(reinterpret_cast<ValueT*>(new char[sizeof(ValueT)*Size])) {}
706 ValueT&
operator[](
const size_t i) {
return mData[i & Mask]; }
707 const ValueT&
operator[](
const size_t i)
const {
return mData[i & Mask]; }
710 for (
size_t i=Size; i; --i) *dst++ = v;
712 ValueT*
data() {
return mData; }
716 const ValueT* src = mData;
717 for (
size_t i=n; i; --i) *dst++ = *src++;
729 #endif // OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED
ConstIterator(const ConstIterator &other)
Definition: PagedArray.h:602
bool operator==(const ConstIterator &other) const
Definition: PagedArray.h:625
ConstIterator & operator++()
Definition: PagedArray.h:609
void sort()
Parallel sort of all the elements in ascending order.
Definition: PagedArray.h:399
static Ptr create()
Return a shared pointer to a new instance of this class.
Definition: PagedArray.h:166
~Page()
Definition: PagedArray.h:703
PagedArrayType & parent() const
Return a reference to the parent PagedArray.
Definition: PagedArray.h:578
PagedArray & operator=(const PagedArray &)=delete
void fill(const ValueType &v)
Set all elements in the page table to the specified value.
Definition: PagedArray.h:245
bool isValid() const
Definition: PagedArray.h:632
Iterator & operator--()
Definition: PagedArray.h:661
Iterator(PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:652
ValueBuffer(const ValueBuffer &other)
Definition: PagedArray.h:553
void copy(ValueType *dst, size_t n) const
Definition: PagedArray.h:715
bool operator>=(const ConstIterator &other) const
Definition: PagedArray.h:627
difference_type operator-(const ConstIterator &other) const
Definition: PagedArray.h:623
~PagedArray()
Destructor removed all allocated pages.
Definition: PagedArray.h:159
bool operator!=(const Iterator &other) const
Definition: PagedArray.h:677
size_t pos() const
Definition: PagedArray.h:684
size_t push_back(const ValueType &value)
This method is deprecated and will be removed shortly!
Definition: PagedArray.h:188
ConstIterator begin() const
Definition: PagedArray.h:385
ConstIterator operator++(int)
Definition: PagedArray.h:612
Iterator()
Definition: PagedArray.h:651
Library and file format version numbers.
bool operator>(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:201
Page()
Definition: PagedArray.h:702
Iterator begin()
Return a non-const iterator pointing to the first element.
Definition: PagedArray.h:373
ConstIterator operator--(int)
Definition: PagedArray.h:613
ValueT * data()
Definition: PagedArray.h:712
void clear()
Removes all elements from the array and delete all pages.
Definition: PagedArray.h:364
const ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:617
ValueT * operator->() const
Definition: PagedArray.h:667
void flush()
Manually transfers the values in this buffer to the parent PagedArray.
Definition: PagedArray.h:572
bool operator!=(const ConstIterator &other) const
Definition: PagedArray.h:626
static size_t memUsage()
Definition: PagedArray.h:700
size_t freeCount() const
Return the number of additional elements that can be added to this array without allocating more memo...
Definition: PagedArray.h:333
ValueT * mData
Definition: PagedArray.h:720
Iterator(const Iterator &other)
Definition: PagedArray.h:653
void push_back(const ValueT &v)
Add a value to the buffer and increment the size.
Definition: PagedArray.h:563
bool operator<(const Tuple< SIZE, T0 > &t0, const Tuple< SIZE, T1 > &t1)
Definition: Tuple.h:189
const ValueT & operator[](const size_t i) const
Definition: PagedArray.h:707
Iterator operator+(const difference_type &pos) const
Definition: PagedArray.h:672
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Multiply m0 by m1 and return the resulting matrix.
Definition: Mat3.h:611
bool operator==(const Iterator &other) const
Definition: PagedArray.h:676
void copy(ValueType *p) const
Definition: PagedArray.h:277
typename BaseT::difference_type difference_type
Definition: PagedArray.h:649
ConstIterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:620
ValueT & operator[](const difference_type &pos) const
Definition: PagedArray.h:668
size_t size() const
Return the current number of elements cached in this buffer.
Definition: PagedArray.h:580
bool operator<=(const Iterator &other) const
Definition: PagedArray.h:679
ConstIterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:619
static size_t pageSize()
Definition: PagedArray.h:581
Iterator operator++(int)
Definition: PagedArray.h:663
ValueType & operator[](size_t i)
Return a reference to the value at the specified offset.
Definition: PagedArray.h:221
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:359
static size_t log2PageSize()
Return log2 of the number of elements per memory page.
Definition: PagedArray.h:342
PagedArray()
Default constructor.
Definition: PagedArray.h:156
ValueT & operator*() const
Definition: PagedArray.h:666
ConstIterator(const PagedArray &parent, size_t pos=0)
Definition: PagedArray.h:601
Concurrent, page-based, dynamically-sized linear data structure with O(1) random access and STL-compl...
Definition: PagedArray.h:143
ConstIterator & operator--()
Definition: PagedArray.h:610
Definition: PagedArray.h:546
size_t pageCount() const
Return the number of allocated memory pages.
Definition: PagedArray.h:336
ConstIterator()
Definition: PagedArray.h:600
difference_type operator-(const Iterator &other) const
Definition: PagedArray.h:674
void invSort()
Parallel sort of all the elements in descending order.
Definition: PagedArray.h:402
static size_t pageSize()
Return the number of elements per memory page.
Definition: PagedArray.h:339
const ValueT & operator*() const
Definition: PagedArray.h:615
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:648
bool isValid() const
Definition: PagedArray.h:683
void resize(size_t size, const ValueType &v)
Resize this array to the specified size and initialize all values to v.
Definition: PagedArray.h:318
Iterator & operator-=(const difference_type &pos)
Definition: PagedArray.h:671
ConstIterator & operator=(const ConstIterator &other)
Definition: PagedArray.h:603
Iterator operator--(int)
Definition: PagedArray.h:664
void resize(size_t size)
Resize this array to the specified size.
Definition: PagedArray.h:293
ValueT & operator[](const size_t i)
Definition: PagedArray.h:706
~ValueBuffer()
Destructor that transfers an buffered values to the parent PagedArray.
Definition: PagedArray.h:555
Iterator & operator=(const Iterator &other)
Definition: PagedArray.h:654
bool operator<=(const ConstIterator &other) const
Definition: PagedArray.h:628
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:153
void fill(const ValueT &v)
Definition: PagedArray.h:708
ConstIterator operator-(const difference_type &pos) const
Definition: PagedArray.h:622
bool isEmpty() const
Return true if the container contains no elements.
Definition: PagedArray.h:351
Definition: PagedArray.h:595
ValueBuffer(PagedArray &parent)
Constructor from a PageArray.
Definition: PagedArray.h:550
size_t push_back_unsafe(const ValueType &value)
Definition: PagedArray.h:198
Page(const Page &)=delete
size_t memUsage() const
Return the memory footprint of this array in bytes.
Definition: PagedArray.h:345
bool operator>=(const Iterator &other) const
Definition: PagedArray.h:678
PagedArray(const PagedArray &)=delete
SharedPtr< PagedArray > Ptr
Definition: PagedArray.h:153
ValueBuffer getBuffer()
Definition: PagedArray.h:179
ValueBuffer & operator=(const ValueBuffer &)=delete
void print(std::ostream &os=std::cout) const
Print information for debugging.
Definition: PagedArray.h:423
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition: version.h:101
Iterator & operator++()
Definition: PagedArray.h:660
Iterator operator-(const difference_type &pos) const
Definition: PagedArray.h:673
ConstIterator operator+(const difference_type &pos) const
Definition: PagedArray.h:621
const ValueType & operator[](size_t i) const
Return a const-reference to the value at the specified offset.
Definition: PagedArray.h:234
Page & operator=(const Page &)=delete
const ValueT * operator->() const
Definition: PagedArray.h:616
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:260
Definition: openvdb/Exceptions.h:13
std::iterator< std::random_access_iterator_tag, ValueT > BaseT
Definition: PagedArray.h:597
Definition: PagedArray.h:696
Iterator end()
Return a non-const iterator pointing to the past-the-last element.
Definition: PagedArray.h:380
Iterator & operator+=(const difference_type &pos)
Definition: PagedArray.h:670
size_t size() const
Return the number of elements in this array.
Definition: PagedArray.h:325
size_t pos() const
Definition: PagedArray.h:633
typename BaseT::difference_type difference_type
Definition: PagedArray.h:598
ConstIterator end() const
Definition: PagedArray.h:395
ValueT ValueType
Definition: PagedArray.h:152
size_t capacity() const
Return the maximum number of elements that this array can contain without allocating more memory page...
Definition: PagedArray.h:329
std::shared_ptr< T > SharedPtr
Definition: openvdb/Types.h:92
Definition: PagedArray.h:646
void sort(Functor func)
Parallel sort of all the elements based on a custom functor with the api:
Definition: PagedArray.h:410