| // Copyright 2022 The Go Authors. All rights reserved. | |
| // Use of this source code is governed by a BSD-style | |
| // license that can be found in the LICENSE file. | |
| package chans | |
| import "runtime" | |
| // Ranger returns a Sender and a Receiver. The Receiver provides a | |
| // Next method to retrieve values. The Sender provides a Send method | |
| // to send values and a Close method to stop sending values. The Next | |
| // method indicates when the Sender has been closed, and the Send | |
| // method indicates when the Receiver has been freed. | |
| // | |
| // This is a convenient way to exit a goroutine sending values when | |
| // the receiver stops reading them. | |
| func Ranger[T any]() (*Sender[T], *Receiver[T]) { | |
| c := make(chan T) | |
| d := make(chan bool) | |
| s := &Sender[T]{values: c, done: d} | |
| r := &Receiver[T]{values: c, done: d} | |
| runtime.SetFinalizer(r, r.finalize) | |
| return s, r | |
| } | |
| // A sender is used to send values to a Receiver. | |
| type Sender[T any] struct { | |
| values chan<- T | |
| done <-chan bool | |
| } | |
| // Send sends a value to the receiver. It returns whether any more | |
| // values may be sent; if it returns false the value was not sent. | |
| func (s *Sender[T]) Send(v T) bool { | |
| select { | |
| case s.values <- v: | |
| return true | |
| case <-s.done: | |
| return false | |
| } | |
| } | |
| // Close tells the receiver that no more values will arrive. | |
| // After Close is called, the Sender may no longer be used. | |
| func (s *Sender[T]) Close() { | |
| close(s.values) | |
| } | |
| // A Receiver receives values from a Sender. | |
| type Receiver[T any] struct { | |
| values <-chan T | |
| done chan<- bool | |
| } | |
| // Next returns the next value from the channel. The bool result | |
| // indicates whether the value is valid, or whether the Sender has | |
| // been closed and no more values will be received. | |
| func (r *Receiver[T]) Next() (T, bool) { | |
| v, ok := <-r.values | |
| return v, ok | |
| } | |
| // finalize is a finalizer for the receiver. | |
| func (r *Receiver[T]) finalize() { | |
| close(r.done) | |
| } | |