55 lines
		
	
	
		
			1.7 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			55 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
 | |
| }
 | 
