1// Copyright 2022 The Go Authors. All rights reserved. 2// Use of this source code is governed by a BSD-style 3// license that can be found in the LICENSE file. 4 5package chans 6 7import "runtime" 8 9// Ranger returns a Sender and a Receiver. The Receiver provides a 10// Next method to retrieve values. The Sender provides a Send method 11// to send values and a Close method to stop sending values. The Next 12// method indicates when the Sender has been closed, and the Send 13// method indicates when the Receiver has been freed. 14// 15// This is a convenient way to exit a goroutine sending values when 16// the receiver stops reading them. 17func Ranger[T any]() (*Sender[T], *Receiver[T]) { 18 c := make(chan T) 19 d := make(chan bool) 20 s := &Sender[T]{values: c, done: d} 21 r := &Receiver[T]{values: c, done: d} 22 runtime.SetFinalizer(r, r.finalize) 23 return s, r 24} 25 26// A sender is used to send values to a Receiver. 27type Sender[T any] struct { 28 values chan<- T 29 done <-chan bool 30} 31 32// Send sends a value to the receiver. It returns whether any more 33// values may be sent; if it returns false the value was not sent. 34func (s *Sender[T]) Send(v T) bool { 35 select { 36 case s.values <- v: 37 return true 38 case <-s.done: 39 return false 40 } 41} 42 43// Close tells the receiver that no more values will arrive. 44// After Close is called, the Sender may no longer be used. 45func (s *Sender[T]) Close() { 46 close(s.values) 47} 48 49// A Receiver receives values from a Sender. 50type Receiver[T any] struct { 51 values <-chan T 52 done chan<- bool 53} 54 55// Next returns the next value from the channel. The bool result 56// indicates whether the value is valid, or whether the Sender has 57// been closed and no more values will be received. 58func (r *Receiver[T]) Next() (T, bool) { 59 v, ok := <-r.values 60 return v, ok 61} 62 63// finalize is a finalizer for the receiver. 64func (r *Receiver[T]) finalize() { 65 close(r.done) 66} 67