diff options
Diffstat (limited to 'slice.go')
| -rw-r--r-- | slice.go | 46 |
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 + } +} |