08bcbddb32
Signed-off-by: Aaron.L.Xu <likexu@harmonycloud.cn>
54 lines
1.7 KiB
Go
54 lines
1.7 KiB
Go
// Package gc experiments with providing central gc tooling to ensure
|
|
// deterministic resource removal within containerd.
|
|
//
|
|
// For now, we just have a single exported implementation that can be used
|
|
// under certain use cases.
|
|
package gc
|
|
|
|
// Tricolor implements basic, single-thread tri-color GC. Given the roots, the
|
|
// complete set and a refs function, this returns the unreachable objects.
|
|
//
|
|
// Correct usage requires that the caller not allow the arguments to change
|
|
// until the result is used to delete objects in the system.
|
|
//
|
|
// It will allocate memory proportional to the size of the reachable set.
|
|
//
|
|
// We can probably use this to inform a design for incremental GC by injecting
|
|
// callbacks to the set modification algorithms.
|
|
func Tricolor(roots []string, all []string, refs func(ref string) []string) []string {
|
|
var (
|
|
grays []string // maintain a gray "stack"
|
|
seen = map[string]struct{}{} // or not "white", basically "seen"
|
|
reachable = map[string]struct{}{} // or "block", in tri-color parlance
|
|
)
|
|
|
|
grays = append(grays, roots...)
|
|
|
|
for len(grays) > 0 {
|
|
// Pick any gray object
|
|
id := grays[len(grays)-1] // effectively "depth first" because first element
|
|
grays = grays[:len(grays)-1]
|
|
seen[id] = struct{}{} // post-mark this as not-white
|
|
|
|
// mark all the referenced objects as gray
|
|
for _, target := range refs(id) {
|
|
if _, ok := seen[target]; !ok {
|
|
grays = append(grays, target)
|
|
}
|
|
}
|
|
|
|
// mark as black when done
|
|
reachable[id] = struct{}{}
|
|
}
|
|
|
|
// All black objects are now reachable, and all white objects are
|
|
// unreachable. Free those that are white!
|
|
var whites []string
|
|
for _, obj := range all {
|
|
if _, ok := reachable[obj]; !ok {
|
|
whites = append(whites, obj)
|
|
}
|
|
}
|
|
|
|
return whites
|
|
}
|