diff options
Diffstat (limited to 'src/common/range_sets.inc')
| -rw-r--r-- | src/common/range_sets.inc | 33 |
1 files changed, 15 insertions, 18 deletions
diff --git a/src/common/range_sets.inc b/src/common/range_sets.inc index 3edd8c8a43..57b07d05f6 100644 --- a/src/common/range_sets.inc +++ b/src/common/range_sets.inc @@ -116,28 +116,25 @@ struct OverlapRangeSet<AddressType>::OverlapRangeSetImpl { } AddressType end_address = base_address + static_cast<AddressType>(size); IntervalType interval{base_address, end_address}; - bool any_removals = false; m_split_ranges_set += std::make_pair(interval, -amount); - do { - any_removals = false; - auto it = m_split_ranges_set.lower_bound(interval); - if (it == m_split_ranges_set.end()) { - return; + // One pass, erasing the segments that dropped to zero or below in address order (the + // search restarted after every erase: quadratic in the segments of the range, and the + // GPU fencing thread does this for each downloaded buffer range while holding the buffer + // cache's lock). Erasing a node leaves the other iterators valid. + auto it = m_split_ranges_set.lower_bound(interval); + const auto end_it = m_split_ranges_set.upper_bound(interval); + while (it != end_it) { + if (it->second > 0) { + ++it; + continue; } - auto end_it = m_split_ranges_set.upper_bound(interval); - for (; it != end_it; it++) { - if (it->second <= 0) { - if constexpr (has_on_delete) { - if (it->second == 0) { - on_delete(it->first.lower(), it->first.upper()); - } - } - any_removals = true; - m_split_ranges_set.erase(it); - break; + if constexpr (has_on_delete) { + if (it->second == 0) { + on_delete(it->first.lower(), it->first.upper()); } } - } while (any_removals); + m_split_ranges_set.erase(it++); + } } template <typename Func> |
