From 5accf50ec467aa14e9dcf7541c2ca0c8ab1a497b Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 17 Aug 2024 23:12:36 -0400 Subject: ConstSlice --- slice.go | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) create mode 100644 slice.go (limited to 'slice.go') 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 + } +} -- cgit v1.2.3