aboutsummaryrefslogtreecommitdiff
path: root/src/common
diff options
context:
space:
mode:
Diffstat (limited to 'src/common')
-rw-r--r--src/common/range_sets.inc33
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>