sync: Select, Combine work with more channel types

This commit is contained in:
Sasha Koshka 2024-12-04 20:00:19 -05:00
parent 09aa19e7c1
commit 0f9d8fb102

View File

@ -4,9 +4,15 @@ import "slices"
import "context" import "context"
import "reflect" import "reflect"
// ChannelRecv is a type constraint that includes all channel types that can be
// recieved from.
type ChannelRecv[T any] interface {
~chan T | ~<- chan T
}
// A type-safe wrapper around reflect.Select. Taken from: // A type-safe wrapper around reflect.Select. Taken from:
// https://stackoverflow.com/questions/19992334 // https://stackoverflow.com/questions/19992334
func Select[T any] (ctx context.Context, channels ...chan T) (int, T, bool) { func Select[T any, C ChannelRecv[T]] (ctx context.Context, channels ...C) (int, T, bool) {
var zero T var zero T
// add all channels as select cases // add all channels as select cases
@ -39,11 +45,12 @@ func Select[T any] (ctx context.Context, channels ...chan T) (int, T, bool) {
return chosen, ret, true return chosen, ret, true
} }
return chosen, zero, false return chosen, zero, false
} }
// Combine returns a channel that continuously returns the result of the select // Combine returns a channel that continuously returns the result of the select
// until all input sources are exhauste, or the context is canceled. // until all input sources are exhauste, or the context is canceled.
func Combine[T any] (ctx context.Context, channels ...chan T) <- chan T { func Combine[T any, C ChannelRecv[T]] (ctx context.Context, channels ...C) <- chan T {
channel := make(chan T) channel := make(chan T)
// our silly slection routine // our silly slection routine
go func () { go func () {