Skip to content

Instantly share code, notes, and snippets.

@clarkmcc
Created April 17, 2020 00:06
Show Gist options
  • Save clarkmcc/b2e6b548312a55091bca527a34cc5f3b to your computer and use it in GitHub Desktop.
Save clarkmcc/b2e6b548312a55091bca527a34cc5f3b to your computer and use it in GitHub Desktop.
StopInformerMap provides an easy interface for interacting with named stop informers
package concurrency
import (
"sync"
)
// StopInformerMap provides an easy interface for interacting with named stop informers
type StopInformerMap interface {
// Starts a new named stop informer
Start(name string, informer StopInformer)
// Starts a new named stop informer and returns it for method chaining
StartAndReturn(name string, informer StopInformer) StopInformer
// Returns a stop informer
Get(name string) StopInformer
// Returns whether a stop informer exists
Exists(name string) bool
// Iterates over all stop informers and sends the stop notification to each; this method
// blocks until all informers acknowledge the stop command
StopAll()
// Iterates over all stop informers and sends the stop notification to each; this method
// returns a channel and sends a value when all informers acknowledge they're stopped
StopAllAndNotify(buffer int) SingleStructChan
}
type genericStopInformerMap struct {
informers map[string]StopInformer
m *sync.RWMutex
}
func NewGenericStopInformerMap() StopInformerMap {
return &genericStopInformerMap{
informers: map[string]StopInformer{},
m: &sync.RWMutex{},
}
}
// Starts a new named stop informer
func (g *genericStopInformerMap) Start(name string, informer StopInformer) {
g.m.Lock()
defer g.m.Unlock()
g.informers[name] = informer
}
// Starts a new named stop informer and returns it for method chaining
func (g *genericStopInformerMap) StartAndReturn(name string, informer StopInformer) StopInformer {
g.m.Lock()
defer g.m.Unlock()
g.informers[name] = informer
return informer
}
// Returns a stop informer
func (g *genericStopInformerMap) Get(name string) StopInformer {
g.m.RLock()
defer g.m.RUnlock()
if i, ok := g.informers[name]; ok {
return i
}
return NewGenericStopInformer().ResolveImmediately()
}
// Returns whether a stop informer exists
func (g *genericStopInformerMap) Exists(name string) bool {
g.m.RLock()
defer g.m.RUnlock()
if _, ok := g.informers[name]; ok {
return true
}
return false
}
// Iterates over all stop informers and sends the stop notification to each; this method
// blocks until all informers acknowledge the stop command
func (g *genericStopInformerMap) StopAll() {
g.m.Lock()
defer g.m.Unlock()
for key, informer := range g.informers {
informer.Stop()
delete(g.informers, key)
}
}
// Iterates over all stop informers and sends the stop notification to each; this method
// returns a channel and sends a value when all informers acknowledge they're stopped
func (g *genericStopInformerMap) StopAllAndNotify(buffer int) SingleStructChan {
g.m.Lock()
defer g.m.Unlock()
notifyChan := make(SingleStructChan, buffer)
wg := &sync.WaitGroup{}
for _, informer := range g.informers {
wg.Add(1)
go func(informer StopInformer, wg *sync.WaitGroup) {
defer wg.Done()
<- informer.StopAndNotify(0)
}(informer, wg)
}
go func() {
wg.Done()
notifyChan <- struct{}{}
}()
return notifyChan
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment