// simultaneously.
func Pull[V any](seq Seq[V]) (next func() (V, bool), stop func()) {
var (
- v V
- ok bool
- done bool
- racer int
+ v V
+ ok bool
+ done bool
+ yieldNext bool
+ racer int
)
c := newcoro(func(c *coro) {
race.Acquire(unsafe.Pointer(&racer))
if done {
return false
}
+ if !yieldNext {
+ panic("iter.Pull: yield called again before next")
+ }
+ yieldNext = false
v, ok = v1, true
race.Release(unsafe.Pointer(&racer))
coroswitch(c)
if done {
return
}
+ if yieldNext {
+ panic("iter.Pull: next called again before yield")
+ }
+ yieldNext = true
race.Release(unsafe.Pointer(&racer))
coroswitch(c)
race.Acquire(unsafe.Pointer(&racer))
// simultaneously.
func Pull2[K, V any](seq Seq2[K, V]) (next func() (K, V, bool), stop func()) {
var (
- k K
- v V
- ok bool
- done bool
- racer int
+ k K
+ v V
+ ok bool
+ done bool
+ yieldNext bool
+ racer int
)
c := newcoro(func(c *coro) {
race.Acquire(unsafe.Pointer(&racer))
if done {
return false
}
+ if !yieldNext {
+ panic("iter.Pull2: yield called again before next")
+ }
+ yieldNext = false
k, v, ok = k1, v1, true
race.Release(unsafe.Pointer(&racer))
coroswitch(c)
if done {
return
}
+ if yieldNext {
+ panic("iter.Pull2: next called again before yield")
+ }
+ yieldNext = true
race.Release(unsafe.Pointer(&racer))
coroswitch(c)
race.Acquire(unsafe.Pointer(&racer))
})
}
}
+
+func TestPullDoubleNext(t *testing.T) {
+ next, _ := Pull(doDoubleNext())
+ nextSlot = next
+ next()
+ if nextSlot != nil {
+ t.Fatal("double next did not fail")
+ }
+}
+
+var nextSlot func() (int, bool)
+
+func doDoubleNext() Seq[int] {
+ return func(_ func(int) bool) {
+ defer func() {
+ if recover() != nil {
+ nextSlot = nil
+ }
+ }()
+ nextSlot()
+ }
+}
+
+func TestPullDoubleNext2(t *testing.T) {
+ next, _ := Pull2(doDoubleNext2())
+ nextSlot2 = next
+ next()
+ if nextSlot2 != nil {
+ t.Fatal("double next did not fail")
+ }
+}
+
+var nextSlot2 func() (int, int, bool)
+
+func doDoubleNext2() Seq2[int, int] {
+ return func(_ func(int, int) bool) {
+ defer func() {
+ if recover() != nil {
+ nextSlot2 = nil
+ }
+ }()
+ nextSlot2()
+ }
+}
+
+func TestPullDoubleYield(t *testing.T) {
+ _, stop := Pull(storeYield())
+ defer func() {
+ if recover() != nil {
+ yieldSlot = nil
+ }
+ stop()
+ }()
+ yieldSlot(5)
+ if yieldSlot != nil {
+ t.Fatal("double yield did not fail")
+ }
+}
+
+func storeYield() Seq[int] {
+ return func(yield func(int) bool) {
+ yieldSlot = yield
+ if !yield(5) {
+ return
+ }
+ }
+}
+
+var yieldSlot func(int) bool
+
+func TestPullDoubleYield2(t *testing.T) {
+ _, stop := Pull2(storeYield2())
+ defer func() {
+ if recover() != nil {
+ yieldSlot2 = nil
+ }
+ stop()
+ }()
+ yieldSlot2(23, 77)
+ if yieldSlot2 != nil {
+ t.Fatal("double yield did not fail")
+ }
+}
+
+func storeYield2() Seq2[int, int] {
+ return func(yield func(int, int) bool) {
+ yieldSlot2 = yield
+ if !yield(23, 77) {
+ return
+ }
+ }
+}
+
+var yieldSlot2 func(int, int) bool