func doTreeWalkP(v types.Value, vr types.ValueReader, cb SomeCallback, concurrency int) { rq := newRefQueue() f := newFailure() visited := map[ref.Ref]bool{} mu := sync.Mutex{} wg := sync.WaitGroup{} var processVal func(v types.Value) processVal = func(v types.Value) { if cb(v) { return } if r, ok := v.(types.RefBase); ok { wg.Add(1) rq.tail() <- r.TargetRef() } else { for _, c := range v.ChildValues() { processVal(c) } } } processRef := func(r ref.Ref) { defer wg.Done() mu.Lock() skip := visited[r] visited[r] = true mu.Unlock() if skip || f.didFail() { return } v := vr.ReadValue(r) if v == nil { f.fail(fmt.Errorf("Attempt to copy absent ref:%s", r.String())) return } processVal(v) } iter := func() { for r := range rq.head() { processRef(r) } } for i := 0; i < concurrency; i++ { go iter() } processVal(v) wg.Wait() rq.close() f.checkNotFailed() }