13 #ifndef OPENVDB_TREE_NODEMANAGER_HAS_BEEN_INCLUDED
14 #define OPENVDB_TREE_NODEMANAGER_HAS_BEEN_INCLUDED
17 #include <tbb/parallel_for.h>
18 #include <tbb/parallel_reduce.h>
29 template<
typename TreeOrLeafManagerT, Index LEVELS = TreeOrLeafManagerT::RootNodeType::LEVEL>
35 template<
typename TreeOrLeafManagerT, Index _LEVELS = TreeOrLeafManagerT::RootNodeType::LEVEL>
46 static bool valid(
size_t) {
return true; }
53 template<
typename NodeT>
73 template <
typename RootT>
96 for (
auto iter = root.beginChildOn(); iter; ++iter) {
97 *nodePtr++ = &iter.getValue();
104 template <
typename ParentsT,
typename NodeFilterT>
105 bool initNodeChildren(ParentsT& parents,
const NodeFilterT& nodeFilter = NodeFilterT(),
bool serial =
false)
109 std::vector<Index32> nodeCounts;
111 nodeCounts.reserve(parents.nodeCount());
112 for (
size_t i = 0; i < parents.nodeCount(); i++) {
113 if (!nodeFilter.valid(i)) nodeCounts.push_back(0);
114 else nodeCounts.push_back(parents(i).childCount());
117 nodeCounts.resize(parents.nodeCount());
122 tbb::blocked_range<Index64>(0, parents.nodeCount(), 64),
123 [&](tbb::blocked_range<Index64>&
range)
125 for (
Index64 i = range.begin(); i < range.end(); i++) {
126 if (!nodeFilter.valid(i)) nodeCounts[i] = 0;
127 else nodeCounts[i] = parents(i).childCount();
135 for (
size_t i = 1; i < nodeCounts.size(); i++) {
136 nodeCounts[i] += nodeCounts[i-1];
139 const size_t nodeCount = nodeCounts.empty() ? 0 : nodeCounts.back();
160 for (
size_t i = 0; i < parents.nodeCount(); i++) {
161 if (!nodeFilter.valid(i))
continue;
162 for (
auto iter = parents(i).beginChildOn(); iter; ++iter) {
163 *nodePtr++ = &iter.getValue();
168 tbb::blocked_range<Index64>(0, parents.nodeCount()),
169 [&](tbb::blocked_range<Index64>&
range)
173 if (i > 0) nodePtr += nodeCounts[i-1];
174 for ( ; i < range.end(); i++) {
175 if (!nodeFilter.valid(i))
continue;
176 for (
auto iter = parents(i).beginChildOn(); iter; ++iter) {
177 *nodePtr++ = &iter.getValue();
192 mEnd(end), mBegin(begin), mGrainSize(grainSize), mNodeList(nodeList) {}
195 mEnd(r.mEnd), mBegin(doSplit(r)), mGrainSize(r.mGrainSize),
196 mNodeList(r.mNodeList) {}
198 size_t size()
const {
return mEnd - mBegin; }
204 bool empty()
const {
return !(mBegin < mEnd);}
220 NodeT&
operator*()
const {
return mRange.mNodeList(mPos); }
224 size_t pos()
const {
return mPos; }
225 bool isValid()
const {
return mPos>=mRange.mBegin && mPos<=mRange.mEnd; }
227 bool test()
const {
return mPos < mRange.mEnd; }
229 operator bool()
const {
return this->
test(); }
234 return (mPos != other.mPos) || (&mRange != &other.mRange);
249 size_t mEnd, mBegin, mGrainSize;
255 size_t middle = r.mBegin + (r.mEnd - r.mBegin) / 2u;
264 return NodeRange(0, this->
nodeCount(), *
this, grainsize);
267 template<
typename NodeOp>
268 void foreach(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
270 NodeTransformerCopy<NodeOp>
transform(op);
271 transform.run(this->
nodeRange(grainSize), threaded);
274 template<
typename NodeOp>
275 void reduce(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
278 transform.run(this->
nodeRange(grainSize), threaded);
283 template<
typename NodeOp>
286 NodeTransformer<NodeOp, OpWithIndex>
transform(op);
287 transform.run(this->
nodeRange(grainSize), threaded);
291 template<
typename NodeOp>
294 NodeReducer<NodeOp, OpWithIndex>
transform(op);
295 transform.run(this->
nodeRange(grainSize), threaded);
302 struct OpWithoutIndex
304 template <
typename T>
305 static void eval(T& node,
typename NodeRange::Iterator& iter) { node(*iter); }
312 template <
typename T>
313 static void eval(T& node,
typename NodeRange::Iterator& iter) { node(*iter, iter.pos()); }
317 template<
typename NodeOp,
typename OpT = OpWithoutIndex>
318 struct NodeTransformerCopy
320 NodeTransformerCopy(
const NodeOp& nodeOp) : mNodeOp(nodeOp)
323 void run(
const NodeRange&
range,
bool threaded =
true)
329 for (
typename NodeRange::Iterator it = range.begin(); it; ++it) {
330 OpT::template
eval(mNodeOp, it);
333 const NodeOp mNodeOp;
337 template<
typename NodeOp,
typename OpT = OpWithoutIndex>
338 struct NodeTransformer
340 NodeTransformer(
const NodeOp& nodeOp) : mNodeOp(nodeOp)
343 void run(
const NodeRange& range,
bool threaded =
true)
349 for (
typename NodeRange::Iterator it = range.begin(); it; ++it) {
350 OpT::template
eval(mNodeOp, it);
353 const NodeOp& mNodeOp;
357 template<
typename NodeOp,
typename OpT = OpWithoutIndex>
360 NodeReducer(NodeOp& nodeOp) : mNodeOp(&nodeOp)
363 NodeReducer(
const NodeReducer& other,
tbb::split)
364 : mNodeOpPtr(std::make_unique<NodeOp>(*(other.mNodeOp), tbb::
split()))
365 , mNodeOp(mNodeOpPtr.
get())
368 void run(
const NodeRange& range,
bool threaded =
true)
370 threaded ? tbb::parallel_reduce(range, *
this) : (*
this)(range);
374 for (
typename NodeRange::Iterator it = range.begin(); it; ++it) {
375 OpT::template
eval(*mNodeOp, it);
378 void join(
const NodeReducer& other)
380 mNodeOp->join(*(other.mNodeOp));
382 std::unique_ptr<NodeOp> mNodeOpPtr;
383 NodeOp *mNodeOp =
nullptr;
401 template<
typename NodeT, Index LEVEL>
412 template <
typename RootT>
415 mList.initRootChildren(root);
419 template<
typename ParentsT>
430 return i==NodeT::LEVEL ?
mList.nodeCount() :
mNext.nodeCount(i);
433 template<
typename NodeOp>
436 mNext.foreachBottomUp(op, threaded, grainSize);
437 mList.foreach(op, threaded, grainSize);
440 template<
typename NodeOp>
443 mList.foreach(op, threaded, grainSize);
444 mNext.foreachTopDown(op, threaded, grainSize);
447 template<
typename NodeOp>
450 mNext.reduceBottomUp(op, threaded, grainSize);
451 mList.reduce(op, threaded, grainSize);
454 template<
typename NodeOp>
457 mList.reduce(op, threaded, grainSize);
458 mNext.reduceTopDown(op, threaded, grainSize);
473 template<
typename NodeT>
482 template <
typename RootT>
485 template<
typename ParentsT>
486 void initNodeChildren(ParentsT& parents,
bool serial =
false) {
mList.initNodeChildren(parents, NodeFilter(), serial); }
492 template<
typename NodeOp>
493 void foreachBottomUp(
const NodeOp& op,
bool threaded,
size_t grainSize)
495 mList.foreach(op, threaded, grainSize);
498 template<
typename NodeOp>
499 void foreachTopDown(
const NodeOp& op,
bool threaded,
size_t grainSize)
501 mList.foreach(op, threaded, grainSize);
504 template<
typename NodeOp>
507 mList.reduce(op, threaded, grainSize);
510 template<
typename NodeOp>
511 void reduceTopDown(NodeOp& op,
bool threaded,
size_t grainSize)
513 mList.reduce(op, threaded, grainSize);
517 NodeList<NodeT>
mList;
529 template<
typename TreeOrLeafManagerT, Index _LEVELS>
535 "expected instantiation of template specialization");
540 static_assert(RootNodeType::LEVEL >=
LEVELS,
"number of levels exceeds root node height");
623 template<
typename NodeOp>
630 template<
typename NodeOp>
697 template<
typename NodeOp>
704 template<
typename NodeOp>
723 template <
typename OpT>
728 , mValidPtr(std::make_unique<bool[]>(size))
729 , mValid(mValidPtr.
get()) { }
733 , mValid(other.mValid) { }
735 template<
typename NodeT>
738 mValid[idx] = mOp(node, idx);
741 bool valid(
size_t idx)
const {
return mValid[idx]; }
743 const OpT&
op()
const {
return mOp; }
747 std::unique_ptr<bool[]> mValidPtr;
748 bool* mValid =
nullptr;
754 template <
typename OpT>
759 , mValidPtr(std::make_unique<bool[]>(size))
760 , mValid(mValidPtr.
get()) { }
764 , mValid(other.mValid) { }
767 : mOpPtr(std::make_unique<OpT>(*(other.mOp), tbb::
split()))
769 , mValid(other.mValid) { }
771 template<
typename NodeT>
774 mValid[idx] = (*mOp)(node, idx);
779 mOp->join(*(other.mOp));
787 OpT&
op() {
return *mOp; }
790 std::unique_ptr<OpT> mOpPtr;
792 std::unique_ptr<bool[]> mValidPtr;
793 bool* mValid =
nullptr;
801 template<
typename NodeT, Index LEVEL>
810 template<
typename NodeOpT,
typename RootT>
812 size_t leafGrainSize,
size_t nonLeafGrainSize)
814 if (!op(root, 0))
return;
815 if (!
mList.initRootChildren(root))
return;
817 mList.foreachWithIndex(filterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
818 mNext.foreachTopDownRecurse(filterOp,
mList, threaded, leafGrainSize, nonLeafGrainSize);
821 template<
typename FilterOpT,
typename ParentT>
823 size_t leafGrainSize,
size_t nonLeafGrainSize)
825 if (!
mList.initNodeChildren(parent, filterOp, !threaded))
return;
826 FilterOpT childFilterOp(filterOp.op(),
mList.nodeCount());
827 mList.foreachWithIndex(childFilterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
828 mNext.foreachTopDownRecurse(childFilterOp,
mList, threaded, leafGrainSize, nonLeafGrainSize);
831 template<
typename NodeOpT,
typename RootT>
833 size_t leafGrainSize,
size_t nonLeafGrainSize)
835 if (!op(root, 0))
return;
836 if (!
mList.initRootChildren(root))
return;
838 mList.reduceWithIndex(filterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
839 mNext.reduceTopDownRecurse(filterOp,
mList, threaded, leafGrainSize, nonLeafGrainSize);
842 template<
typename FilterOpT,
typename ParentT>
844 size_t leafGrainSize,
size_t nonLeafGrainSize)
846 if (!
mList.initNodeChildren(parent, filterOp, !threaded))
return;
847 FilterOpT childFilterOp(filterOp.op(),
mList.nodeCount());
848 mList.reduceWithIndex(childFilterOp, threaded, LEVEL == 0 ? leafGrainSize : nonLeafGrainSize);
849 mNext.reduceTopDownRecurse(childFilterOp,
mList, threaded, leafGrainSize, nonLeafGrainSize);
861 template<
typename NodeT>
867 template<
typename NodeFilterOp,
typename ParentT>
869 size_t leafGrainSize,
size_t )
871 if (!
mList.initNodeChildren(parent, nodeFilterOp, !threaded))
return;
872 mList.foreachWithIndex(nodeFilterOp.op(), threaded, leafGrainSize);
875 template<
typename NodeFilterOp,
typename ParentT>
877 size_t leafGrainSize,
size_t )
879 if (!
mList.initNodeChildren(parent, nodeFilterOp, !threaded))
return;
880 mList.reduceWithIndex(nodeFilterOp.op(), threaded, leafGrainSize);
884 NodeList<NodeT>
mList;
888 template<
typename TreeOrLeafManagerT, Index _LEVELS>
889 class DynamicNodeManager
894 "expected instantiation of template specialization");
899 static_assert(RootNodeType::LEVEL >=
LEVELS,
"number of levels exceeds root node height");
975 template<
typename NodeOp>
977 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1042 template<
typename NodeOp>
1044 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1061 template<
typename TreeOrLeafManagerT>
1069 NodeManager(TreeOrLeafManagerT& tree,
bool =
false) :
mRoot(tree.root()) { }
1078 void rebuild(
bool =
false) { }
1088 template<
typename NodeOp>
1091 template<
typename NodeOp>
1094 template<
typename NodeOp>
1097 template<
typename NodeOp>
1110 template<
typename TreeOrLeafManagerT>
1111 class NodeManager<TreeOrLeafManagerT, 1>
1116 static_assert(RootNodeType::LEVEL > 0,
"expected instantiation of template specialization");
1119 NodeManager(TreeOrLeafManagerT& tree,
bool serial =
false)
1120 :
mRoot(tree.root())
1128 void clear() { mList0.clear(); }
1132 void rebuild(
bool =
false) { mList0.initRootChildren(
mRoot); }
1144 template<
typename NodeOp>
1145 void foreachBottomUp(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1147 mList0.foreach(op, threaded, grainSize);
1151 template<
typename NodeOp>
1152 void foreachTopDown(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1155 mList0.foreach(op, threaded, grainSize);
1158 template<
typename NodeOp>
1159 void reduceBottomUp(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1161 mList0.reduce(op, threaded, grainSize);
1165 template<
typename NodeOp>
1166 void reduceTopDown(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1169 mList0.reduce(op, threaded, grainSize);
1174 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1176 using ListT0 = NodeList<NodeT0>;
1188 template<
typename TreeOrLeafManagerT>
1189 class NodeManager<TreeOrLeafManagerT, 2>
1194 static_assert(RootNodeType::LEVEL > 1,
"expected instantiation of template specialization");
1197 NodeManager(TreeOrLeafManagerT& tree,
bool serial =
false) :
mRoot(tree.root())
1205 void clear() { mList0.clear(); mList1.clear(); }
1209 void rebuild(
bool serial =
false)
1211 mList1.initRootChildren(
mRoot);
1212 mList0.initNodeChildren(mList1, NodeFilter(), serial);
1219 Index64 nodeCount()
const {
return mList0.nodeCount() + mList1.nodeCount(); }
1225 return i==0 ? mList0.nodeCount() : i==1 ? mList1.nodeCount() : 0;
1228 template<
typename NodeOp>
1229 void foreachBottomUp(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1231 mList0.foreach(op, threaded, grainSize);
1232 mList1.foreach(op, threaded, grainSize);
1236 template<
typename NodeOp>
1237 void foreachTopDown(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1240 mList1.foreach(op, threaded, grainSize);
1241 mList0.foreach(op, threaded, grainSize);
1244 template<
typename NodeOp>
1245 void reduceBottomUp(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1247 mList0.reduce(op, threaded, grainSize);
1248 mList1.reduce(op, threaded, grainSize);
1252 template<
typename NodeOp>
1253 void reduceTopDown(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1256 mList1.reduce(op, threaded, grainSize);
1257 mList0.reduce(op, threaded, grainSize);
1262 using NonConstNodeT1 =
typename NodeT2::ChildNodeType;
1264 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1267 using ListT1 = NodeList<NodeT1>;
1268 using ListT0 = NodeList<NodeT0>;
1281 template<
typename TreeOrLeafManagerT>
1282 class NodeManager<TreeOrLeafManagerT, 3>
1287 static_assert(RootNodeType::LEVEL > 2,
"expected instantiation of template specialization");
1290 NodeManager(TreeOrLeafManagerT& tree,
bool serial =
false) :
mRoot(tree.root())
1298 void clear() { mList0.clear(); mList1.clear(); mList2.clear(); }
1302 void rebuild(
bool serial =
false)
1304 mList2.initRootChildren(
mRoot);
1305 mList1.initNodeChildren(mList2, NodeFilter(), serial);
1306 mList0.initNodeChildren(mList1, NodeFilter(), serial);
1313 Index64 nodeCount()
const {
return mList0.nodeCount()+mList1.nodeCount()+mList2.nodeCount(); }
1319 return i==0 ? mList0.nodeCount() : i==1 ? mList1.nodeCount()
1320 : i==2 ? mList2.nodeCount() : 0;
1323 template<
typename NodeOp>
1324 void foreachBottomUp(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1326 mList0.foreach(op, threaded, grainSize);
1327 mList1.foreach(op, threaded, grainSize);
1328 mList2.foreach(op, threaded, grainSize);
1332 template<
typename NodeOp>
1333 void foreachTopDown(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1336 mList2.foreach(op, threaded, grainSize);
1337 mList1.foreach(op, threaded, grainSize);
1338 mList0.foreach(op, threaded, grainSize);
1341 template<
typename NodeOp>
1342 void reduceBottomUp(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1344 mList0.reduce(op, threaded, grainSize);
1345 mList1.reduce(op, threaded, grainSize);
1346 mList2.reduce(op, threaded, grainSize);
1350 template<
typename NodeOp>
1351 void reduceTopDown(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1354 mList2.reduce(op, threaded, grainSize);
1355 mList1.reduce(op, threaded, grainSize);
1356 mList0.reduce(op, threaded, grainSize);
1361 using NonConstNodeT2 =
typename NodeT3::ChildNodeType;
1363 using NonConstNodeT1 =
typename NodeT2::ChildNodeType;
1365 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1368 using ListT2 = NodeList<NodeT2>;
1369 using ListT1 = NodeList<NodeT1>;
1370 using ListT0 = NodeList<NodeT0>;
1384 template<
typename TreeOrLeafManagerT>
1385 class NodeManager<TreeOrLeafManagerT, 4>
1390 static_assert(RootNodeType::LEVEL > 3,
"expected instantiation of template specialization");
1393 NodeManager(TreeOrLeafManagerT& tree,
bool serial =
false) :
mRoot(tree.root())
1401 void clear() { mList0.clear(); mList1.clear(); mList2.clear(); mList3.clear(); }
1405 void rebuild(
bool serial =
false)
1407 mList3.initRootChildren(
mRoot);
1408 mList2.initNodeChildren(mList3, NodeFilter(), serial);
1409 mList1.initNodeChildren(mList2, NodeFilter(), serial);
1410 mList0.initNodeChildren(mList1, NodeFilter(), serial);
1419 return mList0.nodeCount() + mList1.nodeCount()
1420 + mList2.nodeCount() + mList3.nodeCount();
1427 return i==0 ? mList0.nodeCount() : i==1 ? mList1.nodeCount() :
1428 i==2 ? mList2.nodeCount() : i==3 ? mList3.nodeCount() : 0;
1431 template<
typename NodeOp>
1432 void foreachBottomUp(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1434 mList0.foreach(op, threaded, grainSize);
1435 mList1.foreach(op, threaded, grainSize);
1436 mList2.foreach(op, threaded, grainSize);
1437 mList3.foreach(op, threaded, grainSize);
1441 template<
typename NodeOp>
1442 void foreachTopDown(
const NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1445 mList3.foreach(op, threaded, grainSize);
1446 mList2.foreach(op, threaded, grainSize);
1447 mList1.foreach(op, threaded, grainSize);
1448 mList0.foreach(op, threaded, grainSize);
1451 template<
typename NodeOp>
1452 void reduceBottomUp(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1454 mList0.reduce(op, threaded, grainSize);
1455 mList1.reduce(op, threaded, grainSize);
1456 mList2.reduce(op, threaded, grainSize);
1457 mList3.reduce(op, threaded, grainSize);
1461 template<
typename NodeOp>
1462 void reduceTopDown(NodeOp& op,
bool threaded =
true,
size_t grainSize=1)
1465 mList3.reduce(op, threaded, grainSize);
1466 mList2.reduce(op, threaded, grainSize);
1467 mList1.reduce(op, threaded, grainSize);
1468 mList0.reduce(op, threaded, grainSize);
1473 using NonConstNodeT3 =
typename NodeT4::ChildNodeType;
1475 using NonConstNodeT2 =
typename NodeT3::ChildNodeType;
1477 using NonConstNodeT1 =
typename NodeT2::ChildNodeType;
1479 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1482 using ListT3 = NodeList<NodeT3>;
1483 using ListT2 = NodeList<NodeT2>;
1484 using ListT1 = NodeList<NodeT1>;
1485 using ListT0 = NodeList<NodeT0>;
1500 template<
typename TreeOrLeafManagerT>
1501 class DynamicNodeManager<TreeOrLeafManagerT, 0>
1506 static_assert(RootNodeType::LEVEL > 0,
"expected instantiation of template specialization");
1516 template<
typename NodeOp>
1520 if (!op(
mRoot, 0))
return;
1523 template<
typename NodeOp>
1527 if (!op(
mRoot, 0))
return;
1542 template<
typename TreeOrLeafManagerT>
1543 class DynamicNodeManager<TreeOrLeafManagerT, 1>
1548 static_assert(RootNodeType::LEVEL > 0,
"expected instantiation of template specialization");
1558 template<
typename NodeOp>
1560 size_t leafGrainSize=1,
size_t =1)
1563 if (!op(
mRoot, 0))
return;
1565 if (!mList0.initRootChildren(
mRoot))
return;
1566 ForeachFilterOp<NodeOp> nodeOp(op, mList0.nodeCount());
1567 mList0.foreachWithIndex(nodeOp, threaded, leafGrainSize);
1570 template<
typename NodeOp>
1572 size_t leafGrainSize=1,
size_t =1)
1575 if (!op(
mRoot, 0))
return;
1577 if (!mList0.initRootChildren(
mRoot))
return;
1578 ReduceFilterOp<NodeOp> nodeOp(op, mList0.nodeCount());
1579 mList0.reduceWithIndex(nodeOp, threaded, leafGrainSize);
1584 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1586 using ListT0 = NodeList<NodeT0>;
1598 template<
typename TreeOrLeafManagerT>
1599 class DynamicNodeManager<TreeOrLeafManagerT, 2>
1604 static_assert(RootNodeType::LEVEL > 1,
"expected instantiation of template specialization");
1614 template<
typename NodeOp>
1616 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1619 if (!op(
mRoot, 0))
return;
1621 if (!mList1.initRootChildren(
mRoot))
return;
1622 ForeachFilterOp<NodeOp> nodeOp(op, mList1.nodeCount());
1623 mList1.foreachWithIndex(nodeOp, threaded, nonLeafGrainSize);
1625 if (!mList0.initNodeChildren(mList1, nodeOp, !threaded))
return;
1626 mList0.foreachWithIndex(op, threaded, leafGrainSize);
1629 template<
typename NodeOp>
1631 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1634 if (!op(
mRoot, 0))
return;
1636 if (!mList1.initRootChildren(
mRoot))
return;
1637 ReduceFilterOp<NodeOp> nodeOp(op, mList1.nodeCount());
1638 mList1.reduceWithIndex(nodeOp, threaded, nonLeafGrainSize);
1640 if (!mList0.initNodeChildren(mList1, nodeOp, !threaded))
return;
1641 mList0.reduceWithIndex(op, threaded, leafGrainSize);
1646 using NonConstNodeT1 =
typename NodeT2::ChildNodeType;
1648 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1651 using ListT1 = NodeList<NodeT1>;
1652 using ListT0 = NodeList<NodeT0>;
1665 template<
typename TreeOrLeafManagerT>
1666 class DynamicNodeManager<TreeOrLeafManagerT, 3>
1671 static_assert(RootNodeType::LEVEL > 2,
"expected instantiation of template specialization");
1681 template<
typename NodeOp>
1683 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1686 if (!op(
mRoot, 0))
return;
1688 if (!mList2.initRootChildren(
mRoot))
return;
1689 ForeachFilterOp<NodeOp> nodeOp2(op, mList2.nodeCount());
1690 mList2.foreachWithIndex(nodeOp2, threaded, nonLeafGrainSize);
1692 if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))
return;
1693 ForeachFilterOp<NodeOp> nodeOp1(op, mList1.nodeCount());
1694 mList1.foreachWithIndex(nodeOp1, threaded, nonLeafGrainSize);
1696 if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))
return;
1697 mList0.foreachWithIndex(op, threaded, leafGrainSize);
1700 template<
typename NodeOp>
1702 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1705 if (!op(
mRoot, 0))
return;
1707 if (!mList2.initRootChildren(
mRoot))
return;
1708 ReduceFilterOp<NodeOp> nodeOp2(op, mList2.nodeCount());
1709 mList2.reduceWithIndex(nodeOp2, threaded, nonLeafGrainSize);
1711 if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))
return;
1712 ReduceFilterOp<NodeOp> nodeOp1(op, mList1.nodeCount());
1713 mList1.reduceWithIndex(nodeOp1, threaded, nonLeafGrainSize);
1715 if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))
return;
1716 mList0.reduceWithIndex(op, threaded, leafGrainSize);
1721 using NonConstNodeT2 =
typename NodeT3::ChildNodeType;
1723 using NonConstNodeT1 =
typename NodeT2::ChildNodeType;
1725 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1728 using ListT2 = NodeList<NodeT2>;
1729 using ListT1 = NodeList<NodeT1>;
1730 using ListT0 = NodeList<NodeT0>;
1744 template<
typename TreeOrLeafManagerT>
1745 class DynamicNodeManager<TreeOrLeafManagerT, 4>
1750 static_assert(RootNodeType::LEVEL > 3,
"expected instantiation of template specialization");
1760 template<
typename NodeOp>
1762 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1765 if (!op(
mRoot, 0))
return;
1767 if (!mList3.initRootChildren(
mRoot))
return;
1768 ForeachFilterOp<NodeOp> nodeOp3(op, mList3.nodeCount());
1769 mList3.foreachWithIndex(nodeOp3, threaded, nonLeafGrainSize);
1771 if (!mList2.initNodeChildren(mList3, nodeOp3, !threaded))
return;
1772 ForeachFilterOp<NodeOp> nodeOp2(op, mList2.nodeCount());
1773 mList2.foreachWithIndex(nodeOp2, threaded, nonLeafGrainSize);
1775 if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))
return;
1776 ForeachFilterOp<NodeOp> nodeOp1(op, mList1.nodeCount());
1777 mList1.foreachWithIndex(nodeOp1, threaded, nonLeafGrainSize);
1779 if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))
return;
1780 mList0.foreachWithIndex(op, threaded, leafGrainSize);
1783 template<
typename NodeOp>
1785 size_t leafGrainSize=1,
size_t nonLeafGrainSize=1)
1788 if (!op(
mRoot, 0))
return;
1790 if (!mList3.initRootChildren(
mRoot))
return;
1791 ReduceFilterOp<NodeOp> nodeOp3(op, mList3.nodeCount());
1792 mList3.reduceWithIndex(nodeOp3, threaded, nonLeafGrainSize);
1794 if (!mList2.initNodeChildren(mList3, nodeOp3, !threaded))
return;
1795 ReduceFilterOp<NodeOp> nodeOp2(op, mList2.nodeCount());
1796 mList2.reduceWithIndex(nodeOp2, threaded, nonLeafGrainSize);
1798 if (!mList1.initNodeChildren(mList2, nodeOp2, !threaded))
return;
1799 ReduceFilterOp<NodeOp> nodeOp1(op, mList1.nodeCount());
1800 mList1.reduceWithIndex(nodeOp1, threaded, nonLeafGrainSize);
1802 if (!mList0.initNodeChildren(mList1, nodeOp1, !threaded))
return;
1803 mList0.reduceWithIndex(op, threaded, leafGrainSize);
1808 using NonConstNodeT3 =
typename NodeT4::ChildNodeType;
1810 using NonConstNodeT2 =
typename NodeT3::ChildNodeType;
1812 using NonConstNodeT1 =
typename NodeT2::ChildNodeType;
1814 using NonConstNodeT0 =
typename NodeT1::ChildNodeType;
1817 using ListT3 = NodeList<NodeT3>;
1818 using ListT2 = NodeList<NodeT2>;
1819 using ListT1 = NodeList<NodeT1>;
1820 using ListT0 = NodeList<NodeT0>;
1834 #endif // OPENVDB_TREE_NODEMANAGER_HAS_BEEN_INCLUDED
NodeRange(size_t begin, size_t end, const NodeList &nodeList, size_t grainSize=1)
NodeT * operator->() const
Return a pointer to the node to which this iterator is pointing.
void reduceTopDown(NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that processes nodes with a user supplied functor.
void parallel_for(int64_t start, int64_t end, std::function< void(int64_t index)> &&task, parallel_options opt=parallel_options(0, Split_Y, 1))
bool valid(size_t idx) const
static const Index LEVELS
void foreachTopDown(const NodeOpT &op, RootT &root, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
ReduceFilterOp(const ReduceFilterOp &other)
static bool valid(size_t)
Index64 nodeCount() const
Return the total number of cached nodes (excluding the root node)
NodeRange(NodeRange &r, tbb::split)
const NonConstRootNodeType & root() const
Return a reference to the root node.
typename ChildNodeType::ChildNodeType NonConstChildNodeType
void foreachTopDownRecurse(const FilterOpT &filterOp, ParentT &parent, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
NodeT & operator*() const
Return a reference to the node to which this iterator is pointing.
bool is_divisible() const
void reduceTopDown(NodeOpT &op, RootT &root, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
Iterator & operator++()
Advance to the next node.
Iterator(const NodeRange &range, size_t pos)
#define OPENVDB_USE_VERSION_NAMESPACE
ForeachFilterOp(const OpT &op, openvdb::Index64 size)
Index64 nodeCount(Index i) const
**But if you need a or simply need to know when the task has note that the like this
bool valid(size_t idx) const
void reduceTopDown(NodeOp &op, bool threaded, size_t grainSize)
NodeManager(TreeOrLeafManagerT &tree, bool serial=false)
void clear()
Clear all the cached tree nodes.
This class caches tree nodes of a specific type in a linear array.
void reduceTopDown(NodeOp &op, bool threaded=true, size_t leafGrainSize=1, size_t nonLeafGrainSize=1)
Threaded method that processes nodes with a user supplied functor.
ForeachFilterOp(const ForeachFilterOp &other)
NodeT & operator()(size_t n) const
NodeT *& operator[](size_t n)
typename CopyConstness< TreeOrLeafManagerT, NonConstChildNodeType >::Type ChildNodeType
NodeManagerLink()=default
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t leafGrainSize=1, size_t nonLeafGrainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree.
Index64 nodeCount() const
To facilitate threading over the nodes of a tree, cache node pointers in linear arrays, one for each level of the tree.
typename CopyConstness< TreeOrLeafManagerT, NonConstChildNodeType >::Type ChildNodeType
void reduce(NodeOp &op, bool threaded=true, size_t grainSize=1)
void foreachWithIndex(const NodeOp &op, bool threaded=true, size_t grainSize=1)
void rebuild(bool serial=false)
Clear and recache all the tree nodes from the tree. This is required if tree nodes have been added or...
void foreachBottomUp(const NodeOp &op, bool threaded, size_t grainSize)
DynamicNodeManagerLink< ChildNodeType, LEVEL-1 > mNext
void operator()(NodeT &node, size_t idx) const
void foreachBottomUp(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree.
typename RootNodeType::ChildNodeType NonConstChildNodeType
void initRootChildren(RootT &root, bool serial=false)
size_t pos() const
Return the index into the list of the current node.
void operator()(NodeT &node, size_t idx) const
typename std::remove_const< ToType >::type Type
ReduceFilterOp(OpT &op, openvdb::Index64 size)
void reduceBottomUp(NodeOp &op, bool threaded, size_t grainSize)
void foreachTopDown(const NodeOp &op, bool threaded, size_t grainSize)
auto get(const UT_ARTIterator< T > &it) -> decltype(it.key())
void join(const ReduceFilterOp &other)
typename CopyConstness< TreeOrLeafManagerT, NonConstRootNodeType >::Type RootNodeType
HUSD_API bool eval(VtValue &val, T &ret_val)
Index64 nodeCount(Index i) const
Return the number of cached nodes at level i, where 0 corresponds to the lowest level.
bool operator==(const Iterator &other) const
GA_API const UT_StringHolder transform
const RootNodeType & root() const
Return a reference to the root node.
bool initRootChildren(RootT &root)
typename TreeOrLeafManagerT::RootNodeType NonConstRootNodeType
typename CopyConstness< TreeOrLeafManagerT, NonConstRootNodeType >::Type RootNodeType
typename TreeOrLeafManagerT::RootNodeType NonConstRootNodeType
typename CopyConstness< ChildNodeType, NonConstChildNodeType >::Type ChildNodeType
bool initNodeChildren(ParentsT &parents, const NodeFilterT &nodeFilter=NodeFilterT(), bool serial=false)
void reduceBottomUp(NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that processes nodes with a user supplied functor.
DynamicNodeManager(TreeOrLeafManagerT &tree)
Index64 nodeCount() const
static const Index LEVELS
DynamicNodeManagerLink< ChildNodeType, LEVELS-1 > mChain
void initNodeChildren(ParentsT &parents, bool serial=false)
std::unique_ptr< NodeT *[]> mNodePtrs
bool empty() const
Return true if this iterator is exhausted.
typename RootNodeType::ChildNodeType NonConstChildNodeType
This class is a link in a chain that each caches tree nodes of a specific type in a linear array...
Iterator & operator=(const Iterator &)=default
typename CopyConstness< ChildNodeType, NonConstChildNodeType >::Type ChildNodeType
void reduceWithIndex(NodeOp &op, bool threaded=true, size_t grainSize=1)
void OIIO_UTIL_API split(string_view str, std::vector< string_view > &result, string_view sep=string_view(), int maxsplit=-1)
NodeManagerLink< ChildNodeType, LEVEL-1 > mNext
void reduceTopDownRecurse(FilterOpT &filterOp, ParentT &parent, bool threaded, size_t leafGrainSize, size_t nonLeafGrainSize)
ReduceFilterOp(const ReduceFilterOp &other, tbb::split)
const NodeRange & nodeRange() const
This class is a link in a chain that each caches tree nodes of a specific type in a linear array...
DynamicNodeManagerLink()=default
#define OPENVDB_VERSION_NAME
The version namespace name for this library version.
const NodeList & nodeList() const
bool operator!=(const Iterator &other) const
void foreachTopDown(const NodeOp &op, bool threaded=true, size_t grainSize=1)
Threaded method that applies a user-supplied functor to all the nodes in the tree.
NodeRange nodeRange(size_t grainsize=1) const
Return a TBB-compatible NodeRange.
bool test() const
Return true if this iterator is not yet exhausted.
typename ChildNodeType::ChildNodeType NonConstChildNodeType
NodeManagerLink< ChildNodeType, LEVELS-1 > mChain