42 #ifndef OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
43 #define OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
45 #include <boost/shared_ptr.hpp>
46 #include <boost/bind.hpp>
47 #include <boost/function.hpp>
48 #include <tbb/blocked_range.h>
49 #include <tbb/parallel_for.h>
50 #include <openvdb/Types.h>
63 static const bool IsConstTree =
false;
66 template<
typename TreeT>
struct TreeTraits<const TreeT> {
67 static const bool IsConstTree =
true;
77 template<
typename ManagerT>
80 typedef typename ManagerT::RangeType
RangeT;
81 typedef typename ManagerT::LeafType
LeafT;
82 typedef typename ManagerT::BufferType
BufT;
85 LeafT** leafs, BufT* bufs,
size_t bufsPerLeaf)
87 for (
size_t n = r.begin(), m = r.end(), N = bufsPerLeaf; n != m; ++n) {
88 leafs[n]->swap(bufs[n * N + auxBufferIdx]);
108 template<
typename TreeT>
134 assert(this->isValid());
138 mRange = other.mRange; mPos = other.mPos;
return *
this;
143 LeafType&
operator*()
const {
return mRange.mLeafManager.leaf(mPos); }
150 return mRange.mLeafManager.getBuffer(mPos, bufferIdx);
153 size_t pos()
const {
return mPos; }
154 bool isValid()
const {
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
156 bool test()
const {
return mPos < mRange.mEnd; }
158 operator bool()
const {
return this->test(); }
160 bool empty()
const {
return !this->test(); }
163 return (mPos != other.mPos) || (&mRange != &other.mRange);
174 mEnd(end), mBegin(begin), mGrainSize(grainSize), mLeafManager(leafManager) {}
180 size_t size()
const {
return mEnd - mBegin; }
186 bool empty()
const {
return !(mBegin < mEnd);}
191 mEnd(r.mEnd), mBegin(doSplit(r)), mGrainSize(r.mGrainSize),
192 mLeafManager(r.mLeafManager) {}
195 size_t mEnd, mBegin, mGrainSize;
201 size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
209 LeafManager(TreeType& tree,
size_t auxBuffersPerLeaf=0,
bool serial=
false):
213 mAuxBuffersPerLeaf(auxBuffersPerLeaf),
219 this->rebuild(serial);
227 mLeafCount(other.mLeafCount),
228 mAuxBufferCount(other.mAuxBufferCount),
229 mAuxBuffersPerLeaf(other.mAuxBuffersPerLeaf),
230 mLeafs(other.mLeafs),
231 mAuxBuffers(other.mAuxBuffers),
241 delete [] mAuxBuffers;
252 this->initLeafArray();
253 this->initAuxBuffers(serial);
256 void rebuild(
size_t auxBuffersPerLeaf,
bool serial=
false)
259 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
260 this->rebuild(serial);
262 void rebuild(TreeType& tree,
bool serial=
false)
265 this->rebuild(serial);
267 void rebuild(TreeType& tree,
size_t auxBuffersPerLeaf,
bool serial=
false)
270 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
271 this->rebuild(serial);
274 void rebuildAuxBuffers(
size_t auxBuffersPerLeaf,
bool serial=
false)
280 mAuxBuffersPerLeaf = auxBuffersPerLeaf;
281 this->initAuxBuffers(serial);
289 this->removeAuxBuffers();
290 this->initLeafArray();
302 const TreeType&
tree()
const {
return *mTree; }
305 TreeType&
tree() {
return *mTree; }
308 const RootNodeType&
root()
const {
return mTree->root(); }
311 RootNodeType&
root() {
return mTree->root(); }
318 LeafType&
leaf(
size_t leafIdx)
const { assert(leafIdx<mLeafCount);
return *mLeafs[leafIdx]; }
330 BufferType&
getBuffer(
size_t leafIdx,
size_t bufferIdx)
const
332 assert(leafIdx < mLeafCount);
333 assert(bufferIdx == 0 || bufferIdx - 1 < mAuxBuffersPerLeaf);
334 return bufferIdx == 0 ? mLeafs[leafIdx]->buffer()
335 : mAuxBuffers[leafIdx * mAuxBuffersPerLeaf + bufferIdx - 1];
342 RangeType
getRange(
size_t grainsize = 1)
const {
return RangeType(0, mLeafCount, grainsize); }
347 return LeafRange(0, mLeafCount, *
this, grainsize);
361 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf || this->isConstTree())
return false;
362 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, bufferIdx - 1);
363 this->cook(serial ? 0 : 512);
370 bool swapBuffer(
size_t bufferIdx1,
size_t bufferIdx2,
bool serial =
false)
372 const size_t b1 =
std::min(bufferIdx1, bufferIdx2);
373 const size_t b2 =
std::max(bufferIdx1, bufferIdx2);
374 if (b1 == b2 || b2 > mAuxBuffersPerLeaf)
return false;
376 if (this->isConstTree())
return false;
377 mTask = boost::bind(&LeafManager::doSwapLeafBuffer, _1, _2, b2-1);
379 mTask = boost::bind(&LeafManager::doSwapAuxBuffer, _1, _2, b1-1, b2-1);
381 this->cook(serial ? 0 : 512);
395 if (bufferIdx == 0 || bufferIdx > mAuxBuffersPerLeaf)
return false;
396 mTask = boost::bind(&LeafManager::doSyncAuxBuffer, _1, _2, bufferIdx - 1);
397 this->cook(serial ? 0 : 64);
406 switch (mAuxBuffersPerLeaf) {
407 case 0:
return false;
408 case 1: mTask = boost::bind(&LeafManager::doSyncAllBuffers1, _1, _2);
break;
409 case 2: mTask = boost::bind(&LeafManager::doSyncAllBuffers2, _1, _2);
break;
410 default: mTask = boost::bind(&LeafManager::doSyncAllBuffersN, _1, _2);
break;
412 this->cook(serial ? 0 : 64);
475 template<
typename LeafOp>
476 void foreach(
const LeafOp& op,
bool threaded =
true,
size_t grainSize=1)
478 LeafTransformer<LeafOp> transform(op);
479 transform.run(this->leafRange(grainSize), threaded);
483 template<
typename ArrayT>
486 typedef typename ArrayT::value_type T;
487 BOOST_STATIC_ASSERT(boost::is_pointer<T>::value);
488 typedef typename boost::mpl::if_<boost::is_const<typename boost::remove_pointer<T>::type>,
489 const LeafType, LeafType>::type LeafT;
492 if (boost::is_same<T, LeafT*>::value) {
493 array.resize(mLeafCount);
494 for (
size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
496 mTree->getNodes(array);
501 template<
typename ArrayT>
504 typedef typename ArrayT::value_type T;
505 BOOST_STATIC_ASSERT(boost::is_pointer<T>::value);
506 BOOST_STATIC_ASSERT(boost::is_const<
typename boost::remove_pointer<T>::type>::value);
509 if (boost::is_same<T, const LeafType*>::value) {
510 array.resize(mLeafCount);
511 for (
size_t i=0; i<mLeafCount; ++i) array[i] = reinterpret_cast<T>(mLeafs[i]);
513 mTree->getNodes(array);
524 if (mTask) mTask(const_cast<LeafManager*>(
this), r);
536 typedef LeafType* value_type;
538 MyArray(value_type* array) : ptr(array) {}
539 void push_back(value_type leaf) { *ptr++ = leaf; }
544 const size_t leafCount = mTree->leafCount();
545 if (leafCount != mLeafCount) {
547 mLeafs = (leafCount == 0) ? NULL :
new LeafType*[leafCount];
548 mLeafCount = leafCount;
554 void initAuxBuffers(
bool serial)
556 const size_t auxBufferCount = mLeafCount * mAuxBuffersPerLeaf;
557 if (auxBufferCount != mAuxBufferCount) {
558 delete [] mAuxBuffers;
559 mAuxBuffers = (auxBufferCount == 0) ? NULL :
new NonConstBufferType[auxBufferCount];
560 mAuxBufferCount = auxBufferCount;
562 this->syncAllBuffers(serial);
565 void cook(
size_t grainsize)
568 tbb::parallel_for(this->getRange(grainsize), *
this);
570 (*this)(this->getRange());
574 void doSwapLeafBuffer(
const RangeType& r,
size_t auxBufferIdx)
576 LeafManagerImpl<LeafManager>::doSwapLeafBuffer(
577 r, auxBufferIdx, mLeafs, mAuxBuffers, mAuxBuffersPerLeaf);
580 void doSwapAuxBuffer(
const RangeType& r,
size_t auxBufferIdx1,
size_t auxBufferIdx2)
582 for (
size_t N = mAuxBuffersPerLeaf, n = N*r.begin(), m = N*r.end(); n != m; n+=N) {
583 mAuxBuffers[n + auxBufferIdx1].swap(mAuxBuffers[n + auxBufferIdx2]);
587 void doSyncAuxBuffer(
const RangeType& r,
size_t auxBufferIdx)
589 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
590 mAuxBuffers[n*N + auxBufferIdx] = mLeafs[n]->buffer();
594 void doSyncAllBuffers1(
const RangeType& r)
596 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
597 mAuxBuffers[n] = mLeafs[n]->buffer();
601 void doSyncAllBuffers2(
const RangeType& r)
603 for (
size_t n = r.begin(), m = r.end(); n != m; ++n) {
604 const BufferType& leafBuffer = mLeafs[n]->buffer();
605 mAuxBuffers[2*n ] = leafBuffer;
606 mAuxBuffers[2*n+1] = leafBuffer;
610 void doSyncAllBuffersN(
const RangeType& r)
612 for (
size_t n = r.begin(), m = r.end(), N = mAuxBuffersPerLeaf; n != m; ++n) {
613 const BufferType& leafBuffer = mLeafs[n]->buffer();
614 for (
size_t i=n*N, j=i+N; i!=j; ++i) mAuxBuffers[i] = leafBuffer;
620 template<
typename LeafOp>
621 struct LeafTransformer
623 LeafTransformer(
const LeafOp& leafOp) : mLeafOp(leafOp) {}
624 void run(
const LeafRange& range,
bool threaded =
true)
626 threaded ? tbb::parallel_for(range, *
this) : (*this)(range);
628 void operator()(
const LeafRange& range)
const
630 for (
typename LeafRange::Iterator it = range.begin(); it; ++it) mLeafOp(*it, it.pos());
632 const LeafOp mLeafOp;
635 typedef typename boost::function<void (LeafManager*, const RangeType&)> FuncType;
638 size_t mLeafCount, mAuxBufferCount, mAuxBuffersPerLeaf;
640 NonConstBufferType* mAuxBuffers;
642 const bool mIsMaster;
647 template<
typename TreeT>
656 LeafT**, BufT*,
size_t )
666 #endif // OPENVDB_TREE_LEAFMANAGER_HAS_BEEN_INCLUDED
Definition: LeafManager.h:126
Useful traits for Tree types.
Definition: LeafManager.h:62
CopyConstness< TreeType, NonConstLeafType >::Type LeafType
Definition: LeafManager.h:116
LeafType LeafNodeType
Definition: LeafManager.h:117
bool operator==(const Iterator &other) const
Definition: LeafManager.h:165
tbb::blocked_range< size_t > RangeType
Definition: LeafManager.h:121
size_t grainsize() const
Definition: LeafManager.h:182
LeafRange(LeafRange &r, tbb::split)
Definition: LeafManager.h:190
const RootNodeType & root() const
Return a const reference to root node associated with this manager.
Definition: LeafManager.h:308
Iterator(const LeafRange &range, size_t pos)
Definition: LeafManager.h:132
Iterator & operator=(const Iterator &other)
Definition: LeafManager.h:136
#define OPENVDB_THROW(exception, message)
Definition: Exceptions.h:97
const LeafRange & leafRange() const
Definition: LeafManager.h:166
bool is_divisible() const
Definition: LeafManager.h:188
This class manages a linear array of pointers to a given tree's leaf nodes, as well as optional auxil...
Definition: LeafManager.h:109
TreeT::LeafCIter LeafIterType
Definition: LeafManager.h:68
Mat3< typename promote< T0, T1 >::type > operator*(const Mat3< T0 > &m0, const Mat3< T1 > &m1)
Matrix multiplication.
Definition: Mat3.h:608
boost::remove_const< ToType >::type Type
Definition: TreeIterator.h:66
RangeType getRange(size_t grainsize=1) const
Return a tbb::blocked_range of leaf array indices.
Definition: LeafManager.h:342
TreeT TreeType
Definition: LeafManager.h:112
TreeT::RootNodeType RootNodeType
Definition: LeafManager.h:114
void getNodes(ArrayT &array)
Definition: LeafManager.h:484
size_t leafCount() const
Return the number of leaf nodes.
Definition: LeafManager.h:299
bool syncAllBuffers(bool serial=false)
Sync up all auxiliary buffers with their corresponding leaf node buffers.
Definition: LeafManager.h:404
size_t size() const
Definition: LeafManager.h:180
static void doSwapLeafBuffer(const RangeT &r, size_t auxBufferIdx, LeafT **leafs, BufT *bufs, size_t bufsPerLeaf)
Definition: LeafManager.h:84
size_t auxBuffersPerLeaf() const
Return the number of auxiliary buffers per leaf node.
Definition: LeafManager.h:296
LeafManager(TreeType &tree, size_t auxBuffersPerLeaf=0, bool serial=false)
Constructor from a tree reference and an auxiliary buffer count (default is no auxiliary buffers) ...
Definition: LeafManager.h:209
TreeType & tree()
Return a reference to the tree associated with this manager.
Definition: LeafManager.h:305
#define OPENVDB_VERSION_NAME
Definition: version.h:43
ManagerT::LeafType LeafT
Definition: LeafManager.h:81
RootNodeType & root()
Return a reference to the root node associated with this manager.
Definition: LeafManager.h:311
bool operator!=(const Iterator &other) const
Definition: LeafManager.h:161
Index32 Index
Definition: Types.h:59
BufferType & buffer(size_t bufferIdx)
Return the nth buffer for the leaf node to which this iterator is pointing, where n = bufferIdx and n...
Definition: LeafManager.h:148
bool test() const
Return true if this iterator is not yet exhausted.
Definition: LeafManager.h:156
LeafRange leafRange(size_t grainsize=1) const
Return a TBB-compatible LeafRange.
Definition: LeafManager.h:345
Iterator & operator++()
Advance to the next leaf node.
Definition: LeafManager.h:141
TreeT::ValueType ValueType
Definition: LeafManager.h:113
Definition: Exceptions.h:39
LeafManager< const TreeT > ManagerT
Definition: LeafManager.h:650
BufferType & getBuffer(size_t leafIdx, size_t bufferIdx) const
Return the leaf or auxiliary buffer for the leaf node at index leafIdx. If bufferIdx is zero...
Definition: LeafManager.h:330
bool swapBuffer(size_t bufferIdx1, size_t bufferIdx2, bool serial=false)
Swap any two buffers for each leaf node.
Definition: LeafManager.h:370
LeafType & operator*() const
Return a reference to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:143
OPENVDB_API Hermite min(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
size_t auxBufferCount() const
Return the total number of allocated auxiliary buffers.
Definition: LeafManager.h:294
void getNodes(ArrayT &array) const
Definition: LeafManager.h:502
LeafType * operator->() const
Return a pointer to the leaf node to which this iterator is pointing.
Definition: LeafManager.h:145
Definition: LeafManager.h:78
ManagerT::RangeType RangeT
Definition: LeafManager.h:80
void rebuild(TreeType &tree, bool serial=false)
Repopulate the leaf array and delete and reallocate auxiliary buffers.
Definition: LeafManager.h:262
LeafRange(size_t begin, size_t end, const LeafManager &leafManager, size_t grainSize=1)
Definition: LeafManager.h:173
virtual ~LeafManager()
Definition: LeafManager.h:237
TreeT::LeafIter LeafIterType
Definition: LeafManager.h:64
bool isConstTree() const
Return true if the tree associated with this manager is immutable.
Definition: LeafManager.h:314
Definition: Exceptions.h:88
Iterator end() const
Definition: LeafManager.h:178
void removeAuxBuffers()
Remove the auxiliary buffers, but don't rebuild the leaf array.
Definition: LeafManager.h:284
void rebuildLeafArray()
Remove the auxiliary buffers and rebuild the leaf array.
Definition: LeafManager.h:287
ManagerT::BufferType BufT
Definition: LeafManager.h:82
void operator()(const RangeType &r) const
Used internally by tbb::parallel_for() - never call it directly!
Definition: LeafManager.h:522
void rebuild(bool serial=false)
(Re)initialize by resizing (if necessary) and repopulating the leaf array and by deleting existing au...
Definition: LeafManager.h:250
LeafType::Buffer NonConstBufferType
Definition: LeafManager.h:119
static void doSwapLeafBuffer(const RangeT &, size_t, LeafT **, BufT *, size_t)
Definition: LeafManager.h:655
ManagerT::RangeType RangeT
Definition: LeafManager.h:651
ManagerT::LeafType LeafT
Definition: LeafManager.h:652
bool syncAuxBuffer(size_t bufferIdx, bool serial=false)
Sync up the specified auxiliary buffer with the corresponding leaf node buffer.
Definition: LeafManager.h:393
OPENVDB_API Hermite max(const Hermite &, const Hermite &)
min and max operations done directly on the compressed data.
bool empty() const
Definition: LeafManager.h:186
bool isValid() const
Definition: LeafManager.h:154
void rebuild(TreeType &tree, size_t auxBuffersPerLeaf, bool serial=false)
Repopulate the leaf array and delete and reallocate auxiliary buffers.
Definition: LeafManager.h:267
bool empty() const
Return true if this iterator is exhausted.
Definition: LeafManager.h:160
ManagerT::BufferType BufT
Definition: LeafManager.h:653
bool swapLeafBuffer(size_t bufferIdx, bool serial=false)
Swap each leaf node's buffer with the nth corresponding auxiliary buffer, where n = bufferIdx...
Definition: LeafManager.h:359
const LeafManager & leafManager() const
Definition: LeafManager.h:184
Definition: LeafManager.h:129
const TreeType & tree() const
Return a const reference to tree associated with this manager.
Definition: LeafManager.h:302
#define OPENVDB_USE_VERSION_NAMESPACE
Definition: version.h:71
leafmgr::TreeTraits< TreeT >::LeafIterType LeafIterType
Definition: LeafManager.h:118
Iterator begin() const
Definition: LeafManager.h:176
LeafType & leaf(size_t leafIdx) const
Return a pointer to the leaf node at index leafIdx in the array.
Definition: LeafManager.h:318
CopyConstness< TreeType, NonConstBufferType >::Type BufferType
Definition: LeafManager.h:120
LeafManager(const LeafManager &other)
Definition: LeafManager.h:225
size_t pos() const
Return the index into the leaf array of the current leaf node.
Definition: LeafManager.h:153
TreeType::LeafNodeType NonConstLeafType
Definition: LeafManager.h:115