diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-08-17 23:12:36 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-08-17 23:12:36 -0400 |
| commit | 5accf50ec467aa14e9dcf7541c2ca0c8ab1a497b (patch) | |
| tree | e2b7a85d9f82de674c0444a0b47d74f6a9a04816 | |
| parent | 6c7506e5c476f49ef2700e45128d81baedeccfc7 (diff) | |
| download | share-0.0.0.zip | |
ConstSlicev0.0.0
| -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 + } +} |