|
| 1 | +// Copyright 2022 The golang.design Initiative Authors. |
| 2 | +// All rights reserved. Use of this source code is governed |
| 3 | +// by a MIT license that can be found in the LICENSE file. |
| 4 | +// |
| 5 | +// Written by Changkun Ou <changkun.de> |
| 6 | + |
| 7 | +package chann |
| 8 | + |
| 9 | +import "runtime" |
| 10 | + |
| 11 | +// Ranger returns a Sender and a Receiver. The Receiver provides a |
| 12 | +// Next method to retrieve values. The Sender provides a Send method |
| 13 | +// to send values and a Close method to stop sending values. The Next |
| 14 | +// method indicates when the Sender has been closed, and the Send |
| 15 | +// method indicates when the Receiver has been freed. |
| 16 | +// |
| 17 | +// This is a convenient way to exit a goroutine sending values when |
| 18 | +// the receiver stops reading them. |
| 19 | +func Ranger[T any]() (*Sender[T], *Receiver[T]) { |
| 20 | + c := New[T]() |
| 21 | + d := New[bool]() |
| 22 | + s := &Sender[T]{values: c, done: d} |
| 23 | + r := &Receiver[T]{values: c, done: d} |
| 24 | + runtime.SetFinalizer(r, func(r *Receiver[T]) { r.finalize() }) |
| 25 | + return s, r |
| 26 | +} |
| 27 | + |
| 28 | +// A sender is used to send values to a Receiver. |
| 29 | +type Sender[T any] struct { |
| 30 | + values *Chann[T] |
| 31 | + done *Chann[bool] |
| 32 | +} |
| 33 | + |
| 34 | +// Send sends a value to the receiver. It returns whether any more |
| 35 | +// values may be sent; if it returns false the value was not sent. |
| 36 | +func (s *Sender[T]) Send(v T) bool { |
| 37 | + select { |
| 38 | + case s.values.In() <- v: |
| 39 | + return true |
| 40 | + case <-s.done.Out(): |
| 41 | + return false |
| 42 | + } |
| 43 | +} |
| 44 | + |
| 45 | +// Close tells the receiver that no more values will arrive. |
| 46 | +// After Close is called, the Sender may no longer be used. |
| 47 | +func (s *Sender[T]) Close() { s.values.Close() } |
| 48 | + |
| 49 | +// A Receiver receives values from a Sender. |
| 50 | +type Receiver[T any] struct { |
| 51 | + values *Chann[T] |
| 52 | + done *Chann[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.Out() |
| 60 | + return v, ok |
| 61 | +} |
| 62 | + |
| 63 | +// finalize is a finalizer for the receiver. |
| 64 | +func (r *Receiver[T]) finalize() { r.done.Close() } |
0 commit comments