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 5 package chans 6 7 import "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. 17 func 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. 27 type 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. 34 func (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. 45 func (s *Sender[T]) Close() { 46 close(s.values) 47 } 48 49 // A Receiver receives values from a Sender. 50 type 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. 58 func (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. 64 func (r *Receiver[T]) finalize() { 65 close(r.done) 66 } 67