Add iterators for mq and npq.
All checks were successful
Build & Test / Main (push) Successful in 13s
All checks were successful
Build & Test / Main (push) Successful in 13s
This commit is contained in:
parent
c5dde2ab43
commit
9a15ebed25
16
mq/lib.go
16
mq/lib.go
@ -28,6 +28,7 @@
|
|||||||
package mq
|
package mq
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"iter"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gogs.humancabbage.net/sam/priorityq"
|
"gogs.humancabbage.net/sam/priorityq"
|
||||||
@ -199,3 +200,18 @@ func (s *state[T]) trySend(value T, buf *queue.Q[T]) error {
|
|||||||
s.canRecv.Broadcast()
|
s.canRecv.Broadcast()
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iter returns an iterator that consumes values until the queue is closed.
|
||||||
|
func (s *state[T]) Iter() iter.Seq[T] {
|
||||||
|
return func(yield func(T) bool) {
|
||||||
|
for {
|
||||||
|
t, ok := s.Recv()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !yield(t) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -164,6 +164,30 @@ func TestConcProducerConsumer(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIter(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
q := mq.Make[int](4)
|
||||||
|
q.Send(1)
|
||||||
|
q.Send(2)
|
||||||
|
q.Send(3)
|
||||||
|
q.SendHigh(0)
|
||||||
|
q.Close()
|
||||||
|
i := 0
|
||||||
|
for v := range q.Iter() {
|
||||||
|
if v != i {
|
||||||
|
t.Errorf("expected %d, got %d", i, v)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// to test yield() returning false
|
||||||
|
q = mq.Make[int](4)
|
||||||
|
q.Send(3)
|
||||||
|
for _ = range q.Iter() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func BenchmarkSend(b *testing.B) {
|
func BenchmarkSend(b *testing.B) {
|
||||||
q := mq.Make[int](b.N)
|
q := mq.Make[int](b.N)
|
||||||
b.ResetTimer()
|
b.ResetTimer()
|
||||||
|
16
npq/lib.go
16
npq/lib.go
@ -38,6 +38,7 @@ package npq
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"iter"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"gogs.humancabbage.net/sam/priorityq"
|
"gogs.humancabbage.net/sam/priorityq"
|
||||||
@ -212,3 +213,18 @@ func (s *state[P, T]) validatePriority(priority P) {
|
|||||||
priority, s.min, s.max))
|
priority, s.min, s.max))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Iter returns an iterator that consumes values until the queue is closed.
|
||||||
|
func (s *state[P, T]) Iter() iter.Seq[T] {
|
||||||
|
return func(yield func(T) bool) {
|
||||||
|
for {
|
||||||
|
t, ok := s.Recv()
|
||||||
|
if !ok {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !yield(t) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -186,6 +186,30 @@ func TestConcProducerConsumer(t *testing.T) {
|
|||||||
wg.Wait()
|
wg.Wait()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestIter(t *testing.T) {
|
||||||
|
t.Parallel()
|
||||||
|
q := npq.Make[int, int](4, 0, 16)
|
||||||
|
q.Send(4, 0)
|
||||||
|
q.Send(3, 1)
|
||||||
|
q.Send(2, 2)
|
||||||
|
q.Send(1, 3)
|
||||||
|
q.Close()
|
||||||
|
i := 0
|
||||||
|
for v := range q.Iter() {
|
||||||
|
if v != i {
|
||||||
|
t.Errorf("expected %d, got %d", i, v)
|
||||||
|
}
|
||||||
|
i++
|
||||||
|
}
|
||||||
|
|
||||||
|
// to test yield() returning false
|
||||||
|
q = npq.Make[int, int](4, 0, 16)
|
||||||
|
q.Send(1, 3)
|
||||||
|
for _ = range q.Iter() {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
const highPriority = 2
|
const highPriority = 2
|
||||||
|
|
||||||
func BenchmarkSend(b *testing.B) {
|
func BenchmarkSend(b *testing.B) {
|
||||||
|
Loading…
Reference in New Issue
Block a user