From 6c7506e5c476f49ef2700e45128d81baedeccfc7 Mon Sep 17 00:00:00 2001 From: Sam Anthony Date: Sat, 17 Aug 2024 23:12:23 -0400 Subject: Val --- val.go | 53 +++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 val.go diff --git a/val.go b/val.go new file mode 100644 index 0000000..4d35fb9 --- /dev/null +++ b/val.go @@ -0,0 +1,53 @@ +package share + +// Val is a concurrent interface to a piece of shared data. +// +// A client can read the data by sending a channel via request, and the stored value will +// be sent back via the channel. The client is responsible for closing the channel. +// +// The stored value can be changed by sending the new value via Set. Requests block until +// the first value is received on Set. +// +// Val should be closed after use. +type Val[T any] struct { + Request chan<- chan T + Set chan<- T +} + +func NewVal[T any]() Val[T] { + request := make(chan chan T) + set := make(chan T) + go func() { + val := <-set // wait for initial value + for { + select { + case v, ok := <-set: + if !ok { // closed + return + } + val = v + case req, ok := <-request: + if !ok { // closed + return + } + go func() { // don't wait for client to receive + req <- val + }() + } + } + }() + return Val[T]{request, set} +} + +// Get makes a synchronous request and returns the stored value. +func (v Val[T]) Get() T { + c := make(chan T) + defer close(c) + v.Request <- c + return <-c +} + +func (v Val[T]) Close() { + close(v.Request) + close(v.Set) +} -- cgit v1.2.3