in freelist.go [298:379]
func (f *freelist) RemoveRegion(removed region) {
i := sort.Search(len(f.regions), func(i int) bool {
_, end := f.regions[i].Range()
return removed.id <= end
})
if i < 0 || i >= len(f.regions) {
return
}
current := &f.regions[i]
if current.id == removed.id && current.count == removed.count {
// fast path: entry can be completely removed
f.regions = append(f.regions[:i], f.regions[i+1:]...)
f.avail -= uint(removed.count)
return
}
var total uint
removedStart, removedEnd := removed.Range()
for removedStart < removedEnd && i < len(f.regions) {
current := &f.regions[i]
if removedStart < current.id {
// Gap: advance removedStart, so to deal with holes when removing the all regions
// matching the input region
removedStart = current.id
continue
}
count := uint32(removedEnd - removedStart)
if removedStart == current.id {
if current.count < count {
count = current.count
}
// remove entry:
current.id = current.id + PageID(count)
current.count -= count
if current.count == 0 {
// remove region from freelist -> i will point to next region if
// `removed` overlaps 2 non-merged regions
f.regions = append(f.regions[:i], f.regions[i+1:]...)
} else {
// overlapping region, but old region must be preserved:
i++
}
removedStart += PageID(count)
total += uint(count)
} else {
// split current region in removedStart
keep := uint32(removedStart - current.id)
leftover := region{
id: removedStart,
count: current.count - keep,
}
current.count = keep
// remove sub-region from leftover
if leftover.count < count {
count = leftover.count
}
leftover.id += PageID(count)
leftover.count -= count
total += uint(count)
removedStart += PageID(count)
i++ // advance to next region
// insert new entry into regionList if removed did remove region in
// middle of old region
if leftover.count > 0 {
f.regions = append(f.regions, region{})
copy(f.regions[i+1:], f.regions[i:])
f.regions[i] = leftover
break // no more region to split from
}
}
}
f.avail -= total
}