| // Copyright 2023 The Go Authors. All rights reserved. |
| // Use of this source code is governed by a BSD-style |
| // license that can be found in the LICENSE file. |
| |
| // Tests coroutine switches. |
| |
| //go:build ignore |
| |
| package main |
| |
| import ( |
| "iter" |
| "log" |
| "os" |
| "runtime/trace" |
| "sync" |
| ) |
| |
| func main() { |
| // Start tracing. |
| if err := trace.Start(os.Stdout); err != nil { |
| log.Fatalf("failed to start tracing: %v", err) |
| } |
| |
| // Try simple pull iteration. |
| i := pullRange(100) |
| for { |
| _, ok := i.next() |
| if !ok { |
| break |
| } |
| } |
| |
| // Try bouncing the pull iterator between two goroutines. |
| var wg sync.WaitGroup |
| var iterChans [2]chan intIter |
| wg.Add(2) |
| iterChans[0] = make(chan intIter) |
| iterChans[1] = make(chan intIter) |
| go func() { |
| defer wg.Done() |
| |
| iter := pullRange(100) |
| iterChans[1] <- iter |
| |
| for i := range iterChans[0] { |
| _, ok := i.next() |
| if !ok { |
| close(iterChans[1]) |
| break |
| } |
| iterChans[1] <- i |
| } |
| }() |
| go func() { |
| defer wg.Done() |
| |
| for i := range iterChans[1] { |
| _, ok := i.next() |
| if !ok { |
| close(iterChans[0]) |
| break |
| } |
| iterChans[0] <- i |
| } |
| }() |
| wg.Wait() |
| |
| // End of traced execution. |
| trace.Stop() |
| } |
| |
| func pullRange(n int) intIter { |
| next, stop := iter.Pull(func(yield func(v int) bool) { |
| for i := range n { |
| yield(i) |
| } |
| }) |
| return intIter{next: next, stop: stop} |
| } |
| |
| type intIter struct { |
| next func() (int, bool) |
| stop func() |
| } |