Use simpler implementation without Context for notifier.

This commit is contained in:
Joachim Bauch 2023-01-19 13:00:06 +01:00
parent 0b4e48af3b
commit b17eb584b4
No known key found for this signature in database
GPG key ID: 77C1D22D53E15F02
2 changed files with 39 additions and 25 deletions

View file

@ -29,7 +29,11 @@ import (
type Waiter struct { type Waiter struct {
key string key string
SingleWaiter sw *SingleWaiter
}
func (w *Waiter) Wait(ctx context.Context) error {
return w.sw.Wait(ctx)
} }
type Notifier struct { type Notifier struct {
@ -47,22 +51,15 @@ func (n *Notifier) NewWaiter(key string) *Waiter {
if found { if found {
w := &Waiter{ w := &Waiter{
key: key, key: key,
SingleWaiter: SingleWaiter{ sw: waiter.sw,
ctx: waiter.ctx,
cancel: waiter.cancel,
},
} }
n.waiterMap[key][w] = true n.waiterMap[key][w] = true
return w return w
} }
ctx, cancel := context.WithCancel(context.Background())
waiter = &Waiter{ waiter = &Waiter{
key: key, key: key,
SingleWaiter: SingleWaiter{ sw: newSingleWaiter(),
ctx: ctx,
cancel: cancel,
},
} }
if n.waiters == nil { if n.waiters == nil {
n.waiters = make(map[string]*Waiter) n.waiters = make(map[string]*Waiter)
@ -83,7 +80,7 @@ func (n *Notifier) Reset() {
defer n.Unlock() defer n.Unlock()
for _, w := range n.waiters { for _, w := range n.waiters {
w.cancel() w.sw.cancel()
} }
n.waiters = nil n.waiters = nil
n.waiterMap = nil n.waiterMap = nil
@ -98,7 +95,7 @@ func (n *Notifier) Release(w *Waiter) {
delete(waiters, w) delete(waiters, w)
if len(waiters) == 0 { if len(waiters) == 0 {
delete(n.waiters, w.key) delete(n.waiters, w.key)
w.cancel() w.sw.cancel()
} }
} }
} }
@ -109,7 +106,7 @@ func (n *Notifier) Notify(key string) {
defer n.Unlock() defer n.Unlock()
if w, found := n.waiters[key]; found { if w, found := n.waiters[key]; found {
w.cancel() w.sw.cancel()
delete(n.waiters, w.key) delete(n.waiters, w.key)
delete(n.waiterMap, w.key) delete(n.waiterMap, w.key)
} }

View file

@ -27,19 +27,43 @@ import (
) )
type SingleWaiter struct { type SingleWaiter struct {
ctx context.Context root bool
cancel context.CancelFunc ch chan struct{}
once sync.Once
}
func newSingleWaiter() *SingleWaiter {
return &SingleWaiter{
root: true,
ch: make(chan struct{}),
}
}
func (w *SingleWaiter) subWaiter() *SingleWaiter {
return &SingleWaiter{
ch: w.ch,
}
} }
func (w *SingleWaiter) Wait(ctx context.Context) error { func (w *SingleWaiter) Wait(ctx context.Context) error {
select { select {
case <-w.ctx.Done(): case <-w.ch:
return nil return nil
case <-ctx.Done(): case <-ctx.Done():
return ctx.Err() return ctx.Err()
} }
} }
func (w *SingleWaiter) cancel() {
if !w.root {
return
}
w.once.Do(func() {
close(w.ch)
})
}
type SingleNotifier struct { type SingleNotifier struct {
sync.Mutex sync.Mutex
@ -52,21 +76,14 @@ func (n *SingleNotifier) NewWaiter() *SingleWaiter {
defer n.Unlock() defer n.Unlock()
if n.waiter == nil { if n.waiter == nil {
ctx, cancel := context.WithCancel(context.Background()) n.waiter = newSingleWaiter()
n.waiter = &SingleWaiter{
ctx: ctx,
cancel: cancel,
}
} }
if n.waiters == nil { if n.waiters == nil {
n.waiters = make(map[*SingleWaiter]bool) n.waiters = make(map[*SingleWaiter]bool)
} }
w := &SingleWaiter{ w := n.waiter.subWaiter()
ctx: n.waiter.ctx,
cancel: n.waiter.cancel,
}
n.waiters[w] = true n.waiters[w] = true
return w return w
} }