summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--queue.go49
-rw-r--r--queue_test.go37
2 files changed, 86 insertions, 0 deletions
diff --git a/queue.go b/queue.go
new file mode 100644
index 0000000..5e28412
--- /dev/null
+++ b/queue.go
@@ -0,0 +1,49 @@
+package share
+
+// Queue is a FIFO queue with an unlimited capacity.
+//
+// Closing the Enqueue channel closes the Queue. The Queue waits
+// until all elements have been drained from the Dequeue channel
+// before closing it.
+type Queue[T any] struct {
+ // Sending to Enqueue adds an element to the back of the Queue
+ // and never blocks.
+ Enqueue chan<-T
+
+
+ // Receiving from Dequeue removes an element from the front
+ // of the queue or, if the queue is empty, blocks until an element
+ // is enqueued.
+ Dequeue <-chan T
+}
+
+func NewQueue[T any]() Queue[T] {
+ in, out := make(chan T), make(chan T)
+
+ go func() {
+ defer close(out)
+
+ var queue []T
+
+ for v := range in {
+ queue = append(queue, v)
+
+ for len(queue) > 0 {
+ select {
+ case out <- queue[0]:
+ queue = queue[1:]
+ case v, ok := <-in:
+ if !ok {
+ for _, x := range queue {
+ out <- x
+ }
+ return
+ }
+ queue = append(queue, v)
+ }
+ }
+ }
+ }()
+
+ return Queue[T]{Enqueue: in, Dequeue: out}
+}
diff --git a/queue_test.go b/queue_test.go
new file mode 100644
index 0000000..33666d8
--- /dev/null
+++ b/queue_test.go
@@ -0,0 +1,37 @@
+package share_test
+
+import (
+ "testing"
+
+ "git.samanthony.xyz/share"
+)
+
+func TestQueue(t *testing.T) {
+ q := share.NewQueue[string]()
+
+ vals := []string{"foo", "bar", "baz", "xyz"}
+
+ go func() {
+ for _, v := range vals {
+ q.Enqueue <- v
+ }
+ close(q.Enqueue)
+ }()
+
+ go func() {
+ i := 0
+ for front := range q.Dequeue {
+ t.Log("received", front, "from queue")
+ if i > len(vals)-1 {
+ t.Fatal("received too many elements from queue")
+ }
+ if front != vals[i] {
+ t.Fatalf("received %v from queue; wanted %v", front, vals[i])
+ }
+ i++
+ }
+ if i < len(vals) {
+ t.Fatal("did not receive enough values from queue")
+ }
+ }()
+} \ No newline at end of file