15#ifndef OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED 
   16#define OPENVDB_UTIL_PAGED_ARRAY_HAS_BEEN_INCLUDED 
   18#include <openvdb/version.h> 
   26#include <tbb/spin_mutex.h> 
   27#include <tbb/parallel_for.h> 
   28#include <tbb/parallel_sort.h> 
  142template<
typename ValueT, 
size_t Log2PageSize = 10UL>
 
  146    static_assert(Log2PageSize > 1UL, 
"Expected Log2PageSize > 1");
 
  150    using PageTableT = std::deque<Page*>;
 
  195        const size_t index = mSize.fetch_add(1);
 
  196        if (index >= mCapacity) {
 
  197            mPageTable.push_back( 
new Page() );
 
  200        (*mPageTable[index >> Log2PageSize])[index] = value;
 
 
  219        return (*mPageTable[i>>Log2PageSize])[i];
 
 
  232        return (*mPageTable[i>>Log2PageSize])[i];
 
 
  242        auto op = [&](
const tbb::blocked_range<size_t>& r){
 
  243            for(
size_t i=r.begin(); i!=r.end(); ++i) mPageTable[i]->fill(v);
 
  245        tbb::parallel_for(tbb::blocked_range<size_t>(0, this->
pageCount()), op);
 
 
  257        size_t last_page = count >> Log2PageSize;
 
  258        if (last_page >= this->
pageCount()) 
return false;
 
  259        auto op = [&](
const tbb::blocked_range<size_t>& r){
 
  260            for (
size_t i=r.begin(); i!=r.end(); ++i) {
 
  265            tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page, 32), op);
 
  266            mPageTable[last_page]->copy(p+last_page*
Page::Size, m);
 
  268            tbb::parallel_for(tbb::blocked_range<size_t>(0, last_page+1, 32), op);
 
 
  291        if (
size > mCapacity) {
 
 
  320    size_t size()
 const { 
return mSize; }
 
  361        for (
size_t i=0, n=mPageTable.size(); i<n; ++i) 
delete mPageTable[i];
 
  362        PageTableT().swap(mPageTable);
 
 
  394    void sort() { tbb::parallel_sort(this->
begin(), this->
end(), std::less<ValueT>() ); }
 
  397    void invSort() { tbb::parallel_sort(this->
begin(), this->
end(), std::greater<ValueT>()); }
 
  404    template <
typename Functor>
 
  405    void sort(Functor func) { tbb::parallel_sort(this->
begin(), this->
end(), func ); }
 
  418    void print(std::ostream& os = std::cout)
 const 
  420          os << 
"PagedArray:\n" 
  421             << 
"\tSize:       " << this->
size() << 
" elements\n" 
  422             << 
"\tPage table: " << this->
pageCount() << 
" pages\n" 
  423             << 
"\tPage size:  " << this->
pageSize() << 
" elements\n" 
  424             << 
"\tCapacity:   " << this->
capacity() << 
" elements\n" 
  425             << 
"\tFootprint:  " << this->
memUsage() << 
" bytes\n";
 
 
  432    void grow(
size_t index)
 
  434        tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
 
  435        while(index >= mCapacity) {
 
  436            mPageTable.push_back( 
new Page() );
 
  441    void add_full(Page*& page, 
size_t size);
 
  443    void add_partially_full(Page*& page, 
size_t size);
 
  445    void add(Page*& page, 
size_t size) {
 
  446        tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
 
  447        if (size == Page::Size) {
 
  448            this->add_full(page, size);
 
  450            this->add_partially_full(page, size);
 
  453    PageTableT mPageTable;
 
  454    std::atomic<size_t> mSize;
 
  456    tbb::spin_mutex mGrowthMutex;
 
 
  461template <
typename ValueT, 
size_t Log2PageSize>
 
  464    if (mPageTable.size() > (mSize >> Log2PageSize) + 1) {
 
  465        tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
 
  466        const size_t pageCount = (mSize >> Log2PageSize) + 1;
 
  468            delete mPageTable.back();
 
  469            mPageTable.pop_back();
 
  470            mCapacity -= Page::Size;
 
 
  475template <
typename ValueT, 
size_t Log2PageSize>
 
  478    if (&other != 
this && !other.
isEmpty()) {
 
  479        tbb::spin_mutex::scoped_lock lock(mGrowthMutex);
 
  481        Page* page = 
nullptr;
 
  482        const size_t size = mSize & Page::Mask; 
 
  484            page = mPageTable.back();
 
  485            mPageTable.pop_back();
 
  489        mPageTable.insert(mPageTable.end(), other.mPageTable.begin(), other.mPageTable.end());
 
  490        mSize          += other.mSize;
 
  491        mCapacity       = Page::Size*mPageTable.size();
 
  494        PageTableT().swap(other.mPageTable);
 
  496        if (page) this->add_partially_full(page, 
size);
 
 
  500template <
typename ValueT, 
size_t Log2PageSize>
 
  501void PagedArray<ValueT, Log2PageSize>::add_full(Page*& page, 
size_t size)
 
  504    if (mSize & Page::Mask) {
 
  505        Page*& tmp = mPageTable.back();
 
  506        std::swap(tmp, page);
 
  508    mPageTable.push_back(page);
 
  509    mCapacity += Page::Size;
 
  514template <
typename ValueT, 
size_t Log2PageSize>
 
  515void PagedArray<ValueT, Log2PageSize>::add_partially_full(Page*& page, 
size_t size)
 
  518    if (
size_t m = mSize & Page::Mask) {
 
  519        ValueT *s = page->data(), *t = mPageTable.back()->data() + m;
 
  520        for (
size_t i=std::min(mSize+size, mCapacity)-mSize; i; --i) *t++ = *s++;
 
  521        if (mSize+size > mCapacity) {
 
  522            mPageTable.push_back( 
new Page() );
 
  523            t = mPageTable.back()->data();
 
  524            for (
size_t i=mSize+size-mCapacity; i; --i) *t++ = *s++;
 
  525            mCapacity += Page::Size;
 
  528        mPageTable.push_back( page );
 
  529        mCapacity += Page::Size;
 
  538template <
typename ValueT, 
size_t Log2PageSize>
 
  559        (*mPage)[mSize++] = v;
 
 
  568        mParent->add(mPage, mSize);
 
  569        if (mPage == 
nullptr) mPage = 
new Page();
 
 
  575    size_t size()
 const { 
return mSize; }
 
  576    static size_t pageSize() { 
return 1UL << Log2PageSize; }
 
 
  587template <
typename ValueT, 
size_t Log2PageSize>
 
  603        mParent=other.mParent;
 
 
  613    const ValueT& 
operator*()
  const { 
return (*mParent)[mPos]; }
 
  628    bool operator< (
const ConstIterator& other)
 const { 
return mPos <  other.mPos; }
 
  629    bool operator> (
const ConstIterator& other)
 const { 
return mPos >  other.mPos; }
 
  631    bool isValid()
 const { 
return mParent != 
nullptr && mPos < mParent->size(); }
 
  632    size_t pos()
   const { 
return mPos; }
 
 
  643template <
typename ValueT, 
size_t Log2PageSize>
 
  659        mParent=other.mParent;
 
 
  684    bool operator< (
const Iterator& other)
 const { 
return mPos <  other.mPos; }
 
  685    bool operator> (
const Iterator& other)
 const { 
return mPos >  other.mPos; }
 
  687    bool isValid()
 const { 
return mParent != 
nullptr && mPos < mParent->size(); }
 
  688    size_t pos()
   const { 
return mPos; }
 
 
  697template <
typename ValueT, 
size_t Log2PageSize>
 
  702    static const size_t Size = 1UL << Log2PageSize;
 
  714        for (
size_t i=
Size; i; --i) *dst++ = v;
 
 
  720        const ValueT* src = 
mData;
 
  721        for (
size_t i=n; i; --i) *dst++ = *src++;
 
 
 
#define OPENVDB_ASSERT(X)
Definition Assert.h:41
Definition PagedArray.h:589
Definition PagedArray.h:645
Definition PagedArray.h:700
Definition PagedArray.h:541
PagedArray< ValueT, Log2PageSize > PagedArrayType
Definition PagedArray.h:543
ConstIterator cend() const
Return a const iterator pointing to the past-the-last element.
Definition PagedArray.h:389
bool operator>=(const Iterator &other) const
Definition PagedArray.h:682
void copy(ValueType *dst, size_t n) const
Definition PagedArray.h:719
size_t memUsage() const
Return the memory footprint of this array in bytes.
Definition PagedArray.h:340
bool operator==(const ConstIterator &other) const
Definition PagedArray.h:624
Iterator()
Definition PagedArray.h:654
static size_t log2PageSize()
Return log2 of the number of elements per memory page.
Definition PagedArray.h:337
const ValueT & operator[](const difference_type &pos) const
Definition PagedArray.h:615
bool operator>=(const ConstIterator &other) const
Definition PagedArray.h:626
Iterator begin()
Return a non-const iterator pointing to the first element.
Definition PagedArray.h:368
const ValueT & operator[](const size_t i) const
Definition PagedArray.h:711
ConstIterator operator+(const difference_type &pos) const
Definition PagedArray.h:619
size_t size() const
Definition PagedArray.h:320
ValueT & operator[](const size_t i)
Definition PagedArray.h:710
PagedArray(const PagedArray &)=delete
Iterator(const Iterator &other)
Definition PagedArray.h:656
friend ConstIterator operator+(const difference_type &pos, const ConstIterator &other)
Definition PagedArray.h:622
size_t push_back_unsafe(const ValueType &value)
Definition PagedArray.h:193
ValueT & operator[](const difference_type &pos) const
Definition PagedArray.h:671
void copy(ValueType *p) const
Definition PagedArray.h:272
Iterator(PagedArray &parent, size_t pos=0)
Definition PagedArray.h:655
ValueT & reference
Definition PagedArray.h:595
ConstIterator & operator+=(const difference_type &pos)
Definition PagedArray.h:617
difference_type operator-(const ConstIterator &other) const
Definition PagedArray.h:621
ValueT * operator->() const
Definition PagedArray.h:670
static size_t memUsage()
Definition PagedArray.h:704
void sort()
Parallel sort of all the elements in ascending order.
Definition PagedArray.h:394
size_t pageCount() const
Definition PagedArray.h:331
~Page()
Definition PagedArray.h:707
void resize(size_t size)
Resize this array to the specified size.
Definition PagedArray.h:288
ValueT * mData
Definition PagedArray.h:724
void sort(Functor func)
Parallel sort of all the elements based on a custom functor with the api:
Definition PagedArray.h:405
PagedArray()
Default constructor.
Definition PagedArray.h:157
ConstIterator & operator--()
Definition PagedArray.h:608
~ValueBuffer()
Destructor that transfers an buffered values to the parent PagedArray.
Definition PagedArray.h:550
void invSort()
Parallel sort of all the elements in descending order.
Definition PagedArray.h:397
Iterator & operator+=(const difference_type &pos)
Definition PagedArray.h:673
bool isValid() const
Definition PagedArray.h:631
Iterator operator+(const difference_type &pos) const
Definition PagedArray.h:675
void shrink_to_fit()
Reduce the page table to fix the current size.
Definition PagedArray.h:462
ValueBuffer & operator=(const ValueBuffer &)=delete
ValueT & operator*() const
Definition PagedArray.h:669
ConstIterator end() const
Definition PagedArray.h:390
void fill(const ValueType &v)
Set all elements in the page table to the specified value.
Definition PagedArray.h:240
void push_back(const ValueT &v)
Add a value to the buffer and increment the size.
Definition PagedArray.h:558
size_t freeCount() const
Return the number of additional elements that can be added to this array without allocating more memo...
Definition PagedArray.h:328
friend Iterator operator+(const difference_type &pos, const Iterator &other)
Definition PagedArray.h:678
bool operator!=(const Iterator &other) const
Definition PagedArray.h:681
size_t capacity() const
Return the maximum number of elements that this array can contain without allocating more memory page...
Definition PagedArray.h:324
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:354
ValueT ValueType
Definition PagedArray.h:153
ValueT * pointer
Definition PagedArray.h:594
Iterator operator--(int)
Definition PagedArray.h:667
std::random_access_iterator_tag iterator_category
Definition PagedArray.h:591
PagedArray & operator=(const PagedArray &)=delete
void resize(size_t size, const ValueType &v)
Resize this array to the specified size and initialize all values to v.
Definition PagedArray.h:313
ConstIterator & operator-=(const difference_type &pos)
Definition PagedArray.h:618
ValueType & operator[](size_t i)
Return a reference to the value at the specified offset.
Definition PagedArray.h:216
ConstIterator cbegin() const
Return a const iterator pointing to the first element.
Definition PagedArray.h:379
ConstIterator operator-(const difference_type &pos) const
Definition PagedArray.h:620
Iterator & operator-=(const difference_type &pos)
Definition PagedArray.h:674
Page(const Page &)=delete
bool operator!=(const ConstIterator &other) const
Definition PagedArray.h:625
bool operator<=(const Iterator &other) const
Definition PagedArray.h:683
size_t pos() const
Definition PagedArray.h:632
~PagedArray()
Destructor removed all allocated pages.
Definition PagedArray.h:160
Iterator end()
Return a non-const iterator pointing to the past-the-last element.
Definition PagedArray.h:375
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:255
ConstIterator operator++(int)
Definition PagedArray.h:610
difference_type operator-(const Iterator &other) const
Definition PagedArray.h:677
ValueBuffer getBuffer()
Definition PagedArray.h:180
const ValueT & operator*() const
Definition PagedArray.h:613
ValueBuffer(const ValueBuffer &other)
Definition PagedArray.h:548
void merge(PagedArray &other)
Transfer all the elements (and pages) from the other array to this array.
Definition PagedArray.h:476
Iterator operator++(int)
Definition PagedArray.h:666
static const size_t Mask
Definition PagedArray.h:703
SharedPtr< PagedArray > Ptr
Definition PagedArray.h:154
void clear()
Definition PagedArray.h:359
std::ptrdiff_t difference_type
Definition PagedArray.h:593
ValueT * data()
Definition PagedArray.h:716
const ValueT * operator->() const
Definition PagedArray.h:614
bool isEmpty() const
Return true if the container contains no elements.
Definition PagedArray.h:346
const ValueType & operator[](size_t i) const
Return a const-reference to the value at the specified offset.
Definition PagedArray.h:229
PagedArrayType & parent() const
Return a reference to the parent PagedArray.
Definition PagedArray.h:573
Page()
Definition PagedArray.h:706
ConstIterator begin() const
Definition PagedArray.h:380
bool operator<=(const ConstIterator &other) const
Definition PagedArray.h:627
ConstIterator & operator++()
Definition PagedArray.h:607
ConstIterator(const PagedArray &parent, size_t pos=0)
Definition PagedArray.h:599
static const size_t Size
Definition PagedArray.h:702
static Ptr create()
Return a shared pointer to a new instance of this class.
Definition PagedArray.h:167
void flush()
Manually transfers the values in this buffer to the parent PagedArray.
Definition PagedArray.h:567
ValueT value_type
Definition PagedArray.h:592
ConstIterator & operator=(const ConstIterator &other)
Definition PagedArray.h:601
Iterator & operator=(const Iterator &other)
Definition PagedArray.h:657
Iterator & operator++()
Definition PagedArray.h:663
void fill(const ValueT &v)
Definition PagedArray.h:712
ValueBuffer(PagedArray &parent)
Constructor from a PageArray.
Definition PagedArray.h:545
void print(std::ostream &os=std::cout) const
Print information for debugging.
Definition PagedArray.h:418
Iterator & operator--()
Definition PagedArray.h:664
Page & operator=(const Page &)=delete
bool operator==(const Iterator &other) const
Definition PagedArray.h:680
Iterator operator-(const difference_type &pos) const
Definition PagedArray.h:676
ConstIterator()
Definition PagedArray.h:598
ConstIterator operator--(int)
Definition PagedArray.h:611
static size_t pageSize()
Return the number of elements per memory page.
Definition PagedArray.h:334
ConstIterator(const ConstIterator &other)
Definition PagedArray.h:600
std::shared_ptr< T > SharedPtr
Definition Types.h:114
Definition Exceptions.h:13
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
Definition version.h.in:121
#define OPENVDB_USE_VERSION_NAMESPACE
Definition version.h.in:218