@@ -219,31 +219,60 @@ class LeafNode
219219 public SparseIteratorBase<
220220 MaskIterT, ValueIter<MaskIterT, NodeT, ValueT, TagT>, NodeT, ValueT>
221221 {
222+ using ValueType = std::conditional_t <std::is_const_v<NodeT>, ValueT,
223+ std::remove_const_t <ValueT>>;
222224 using BaseT = SparseIteratorBase<MaskIterT, ValueIter, NodeT, ValueT>;
223225
224226 ValueIter () {}
225- ValueIter (const MaskIterT& iter, NodeT* parent): BaseT(iter, parent) {}
227+ ValueIter (const MaskIterT& iter, NodeT* parent)
228+ : BaseT(iter, parent)
229+ // Unlike other value iterators, cache the buffer data as part of
230+ // the iterators members to avoid the cost of going through the
231+ // leaf buffer atomic/checking API
232+ , mData ([&]() { OPENVDB_ASSERT (parent); return parent->buffer ().data (); }()) {}
226233
227- ValueT& getItem (Index pos) const { return this -> parent (). getValue ( pos) ; }
228- ValueT& getValue () const { return this ->parent (). getValue (this ->pos ()); }
234+ ValueT& getItem (Index pos) const { return mData [ pos] ; }
235+ ValueT& getValue () const { return this ->getItem (this ->pos ()); }
229236
230237 // Note: setItem() can't be called on const iterators.
231238 void setItem (Index pos, const ValueT& value) const
232239 {
233- this ->parent ().setValueOnly (pos, value);
240+ if constexpr (std::is_const_v<NodeT>) {
241+ static_assert (!std::is_const_v<NodeT>,
242+ " ValueIter::setItem cannot be called on const iterators" );
243+ }
244+ else {
245+ OPENVDB_ASSERT (pos < SIZE);
246+ OPENVDB_ASSUME (pos < SIZE);
247+ mData [pos] = value;
248+ }
234249 }
235250 // Note: setValue() can't be called on const iterators.
236- void setValue (const ValueT& value) const
237- {
238- this ->parent ().setValueOnly (this ->pos (), value);
239- }
251+ void setValue (const ValueT& value) const { this ->setItem (this ->pos (), value); }
240252
241253 // Note: modifyItem() can't be called on const iterators.
242254 template <typename ModifyOp>
243- void modifyItem (Index n, const ModifyOp& op) const { this ->parent ().modifyValue (n, op); }
255+ void modifyItem (Index n, const ModifyOp& op) const
256+ {
257+ if constexpr (std::is_const_v<NodeT>) {
258+ static_assert (!std::is_const_v<NodeT>,
259+ " ValueIter::modifyItem cannot be called on const iterators" );
260+ }
261+ else {
262+ OPENVDB_ASSERT (n < SIZE);
263+ OPENVDB_ASSUME (n < SIZE);
264+ op (mData [n]);
265+ this ->parent ().setValueOn (n);
266+ }
267+ }
244268 // Note: modifyValue() can't be called on const iterators.
245269 template <typename ModifyOp>
246- void modifyValue (const ModifyOp& op) const { this ->parent ().modifyValue (this ->pos (), op); }
270+ void modifyValue (const ModifyOp& op) const
271+ {
272+ this ->modifyItem (this ->pos (), op);
273+ }
274+ private:
275+ ValueType* mData ;
247276 };
248277
249278 // / Leaf nodes have no children, so their child iterators have no get/set accessors.
0 commit comments