70 lines
1.4 KiB
Text
70 lines
1.4 KiB
Text
|
package gc
|
||
|
|
||
|
type color uint8
|
||
|
|
||
|
const (
|
||
|
white = iota
|
||
|
gray
|
||
|
black
|
||
|
)
|
||
|
|
||
|
func tricolor(roots []string, all []string, refs map[string][]string) []string {
|
||
|
// all objects white -> default value of color
|
||
|
state := make(map[string]color, len(all))
|
||
|
var (
|
||
|
grays []string
|
||
|
reachable []string
|
||
|
)
|
||
|
|
||
|
grays = append(grays, roots...)
|
||
|
// root-set objects gray.
|
||
|
for _, ro := range roots {
|
||
|
state[ro] = gray
|
||
|
}
|
||
|
|
||
|
// (Repeat this as long as there are gray coloured objects) Pick a gray
|
||
|
// object. Colour all objects referenced to from that gray object gray too.
|
||
|
// (Except those who are black). And colour itself black.
|
||
|
|
||
|
// Pick any gray object
|
||
|
for id := findcolor(state, gray); id != ""; id = findcolor(state, gray) {
|
||
|
// mark all the referenced objects as gray
|
||
|
for _, target := range refs[id] {
|
||
|
if state[target] == white {
|
||
|
state[target] = gray
|
||
|
}
|
||
|
}
|
||
|
state[id] = black
|
||
|
}
|
||
|
|
||
|
// 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 state[obj] == white {
|
||
|
whites = append(whites, obj)
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return whites
|
||
|
}
|
||
|
|
||
|
func findcolor(cs map[string]color, q color) string {
|
||
|
// TODO(stevvooe): Super-inefficient!
|
||
|
for id, c := range cs {
|
||
|
if c == q {
|
||
|
return id
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return ""
|
||
|
}
|
||
|
|
||
|
// type colorset struct {
|
||
|
// state map[string]color
|
||
|
// }
|
||
|
|
||
|
// func (cs *colorset) mark(id string, c color) {
|
||
|
// cs.state[id] = c
|
||
|
// }
|