@@ -267,7 +267,7 @@ class NodeList
267
267
template <typename NodeOp>
268
268
void foreach (const NodeOp& op, bool threaded = true , size_t grainSize=1 )
269
269
{
270
- NodeTransformer <NodeOp> transform (op);
270
+ NodeTransformerCopy <NodeOp> transform (op); // always deep-copies the op
271
271
transform.run (this ->nodeRange (grainSize), threaded);
272
272
}
273
273
@@ -278,7 +278,8 @@ class NodeList
278
278
transform.run (this ->nodeRange (grainSize), threaded);
279
279
}
280
280
281
- // identical to foreach except the operator() method has a node index
281
+ // identical to foreach except the operator() method has a node index and
282
+ // the operator is referenced instead of copied in NodeTransformer
282
283
template <typename NodeOp>
283
284
void foreachWithIndex (const NodeOp& op, bool threaded = true , size_t grainSize=1 )
284
285
{
@@ -312,6 +313,26 @@ class NodeList
312
313
static void eval (T& node, typename NodeRange::Iterator& iter) { node (*iter, iter.pos ()); }
313
314
};
314
315
316
+ // Private struct of NodeList that performs parallel_for
317
+ template <typename NodeOp, typename OpT = OpWithoutIndex>
318
+ struct NodeTransformerCopy
319
+ {
320
+ NodeTransformerCopy (const NodeOp& nodeOp) : mNodeOp (nodeOp)
321
+ {
322
+ }
323
+ void run (const NodeRange& range, bool threaded = true )
324
+ {
325
+ threaded ? tbb::parallel_for (range, *this ) : (*this )(range);
326
+ }
327
+ void operator ()(const NodeRange& range) const
328
+ {
329
+ for (typename NodeRange::Iterator it = range.begin (); it; ++it) {
330
+ OpT::template eval (mNodeOp , it);
331
+ }
332
+ }
333
+ const NodeOp mNodeOp ;
334
+ };// NodeList::NodeTransformerCopy
335
+
315
336
// Private struct of NodeList that performs parallel_for
316
337
template <typename NodeOp, typename OpT = OpWithoutIndex>
317
338
struct NodeTransformer
@@ -329,7 +350,7 @@ class NodeList
329
350
OpT::template eval (mNodeOp , it);
330
351
}
331
352
}
332
- const NodeOp mNodeOp ;
353
+ const NodeOp& mNodeOp ;
333
354
};// NodeList::NodeTransformer
334
355
335
356
// Private struct of NodeList that performs parallel_reduce
@@ -886,6 +907,13 @@ class DynamicNodeManager
886
907
// / children of this node should be processed, false indicating the
887
908
// / early-exit termination should occur.
888
909
// /
910
+ // / @note Unlike the NodeManager, the foreach() method of the
911
+ // / DynamicNodeManager uses copy-by-reference for the user-supplied functor.
912
+ // / This can be an issue when using a shared Accessor or shared Sampler in
913
+ // / the operator as they are not inherently thread-safe. For these use
914
+ // / cases, it is recommended to create the Accessor or Sampler in the
915
+ // / operator execution itself.
916
+ // /
889
917
// / @par Example:
890
918
// / @code
891
919
// / // Functor to densify the first child node in a linear array. Note
0 commit comments