diff options
| author | Sam Anthony <sam@samanthony.xyz> | 2024-08-15 16:28:34 -0400 |
|---|---|---|
| committer | Sam Anthony <sam@samanthony.xyz> | 2024-08-15 16:28:34 -0400 |
| commit | 088ab5372f609a2489163844ac58d8b842cedb13 (patch) | |
| tree | 42536640c111700deab27357315ed63c8b01a8d3 | |
| parent | fb44cf37696fa5491dd393336404ee40fe047ccb (diff) | |
| download | gui-088ab5372f609a2489163844ac58d8b842cedb13.zip | |
rename server to sharedVal
| -rw-r--r-- | mux.go | 15 | ||||
| -rw-r--r-- | share.go | 52 | ||||
| -rw-r--r-- | srv.go | 52 |
3 files changed, 59 insertions, 60 deletions
@@ -10,7 +10,7 @@ import ( // events and their draw functions get redirected to the root Env. type Mux struct { addEventsIn chan<- chan<- Event - sizeSrv server[image.Rectangle] + size sharedVal[image.Rectangle] draw chan<- func(draw.Image) image.Rectangle } @@ -20,11 +20,11 @@ type Mux struct { // created by the Mux. func NewMux(env Env) (mux *Mux, master Env) { addEventsIn := make(chan chan<- Event) - sizeSrv := newServer[image.Rectangle]() + size := newSharedVal[image.Rectangle]() drawChan := make(chan func(draw.Image) image.Rectangle) mux = &Mux{ addEventsIn: addEventsIn, - sizeSrv: sizeSrv, + size: size, draw: drawChan, } @@ -33,7 +33,7 @@ func NewMux(env Env) (mux *Mux, master Env) { defer close(env.Draw()) defer close(addEventsIn) - defer sizeSrv.close() + defer size.close() defer func() { for _, eventsIn := range eventsIns { close(eventsIn) @@ -52,7 +52,7 @@ func NewMux(env Env) (mux *Mux, master Env) { return } if resize, ok := e.(Resize); ok { - sizeSrv.update <- resize.Rectangle + size.set <- resize.Rectangle } for _, eventsIn := range eventsIns { eventsIn <- e @@ -88,9 +88,8 @@ func (mux *Mux) makeEnv(master bool) Env { env := &muxEnv{eventsOut, drawChan} mux.addEventsIn <- eventsIn - // make sure to always send a resize event to a new Env if we got the size already - // that means it missed the resize event by the root Env - eventsIn <- Resize{mux.sizeSrv.get()} + // make sure to always send a resize event to a new Env + eventsIn <- Resize{mux.size.get()} go func() { func() { diff --git a/share.go b/share.go new file mode 100644 index 0000000..b370e5a --- /dev/null +++ b/share.go @@ -0,0 +1,52 @@ +package gui + +// sharedVal 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. +// +// A sharedVal should be closed after use. +type sharedVal[T any] struct { + request chan<- chan T + set chan<- T +} + +func newSharedVal[T any]() sharedVal[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 sharedVal[T]{request, set} +} + +// get makes a synchronous request and returns the stored value. +func (sv sharedVal[T]) get() T { + c := make(chan T) + sv.request <- c + return <-c +} + +func (sv sharedVal[T]) close() { + close(sv.request) + close(sv.set) +} @@ -1,52 +0,0 @@ -package gui - -// server is a concurrent interface that stores a value and serves it to clients. -// The stored value can be changed by sending the new value via update. server blocks -// until the first value is received. -// -// A client can read the stored value by sending a channel via request. The server -// responds by sending the value back via the channel. The client is responsible for -// closing the channel. -// -// A server should be closed after use. -type server[T any] struct { - request chan<- chan T - update chan<- T -} - -func newServer[T any]() server[T] { - request := make(chan chan T) - update := make(chan T) - go func() { - val := <-update // wait for initial value - for { - select { - case v, ok := <-update: - 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 server[T]{request, update} -} - -// get makes a synchronous request to the server and returns the stored value. -func (srv server[T]) get() T { - c := make(chan T) - srv.request <- c - return <-c -} - -func (srv server[T]) close() { - close(srv.request) - close(srv.update) -} |