summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--slice.go46
1 files changed, 46 insertions, 0 deletions
diff --git a/slice.go b/slice.go
new file mode 100644
index 0000000..0be8f3e
--- /dev/null
+++ b/slice.go
@@ -0,0 +1,46 @@
+package share
+
+// ConstSlice is a read-only slice that can be shared between goroutines. It should be closed after use.
+type ConstSlice[T any] struct {
+ requests chan<- chan T
+}
+
+// NewConstSlice initializes a ConstSlice with the given slice. The slice is not copied, and thus should not be used
+// again after creating the ConstSlice.
+func NewConstSlice[T any](slc []T) ConstSlice[T] {
+ requests := make(chan chan T)
+ go serve(slc, requests)
+ return ConstSlice[T]{requests}
+}
+
+// Elems returns a channel that yields each successive element of the slice.
+// Once drained, the channel is closed automatically, and therefore should NOT be closed again by the caller.
+func (cs ConstSlice[T]) Elems() <-chan T {
+ elems := make(chan T) // will be closed by request handler
+ cs.requests <- elems
+ c := make(chan T)
+ go func() {
+ defer close(c)
+ for elem := range elems {
+ c <- elem
+ }
+ }()
+ return c
+}
+
+func (cs ConstSlice[T]) Close() {
+ close(cs.requests)
+}
+
+func serve[T any](slc []T, requests <-chan chan T) {
+ for request := range requests {
+ go handle(request, slc)
+ }
+}
+
+func handle[T any](request chan<- T, slc []T) {
+ defer close(request)
+ for _, v := range slc {
+ request <- v
+ }
+}