package singleton import ( "reflect" "strings" "github.com/navidrome/navidrome/log" ) var ( instances = make(map[string]interface{}) getOrCreateC = make(chan *entry, 1) ) type entry struct { constructor func() interface{} object interface{} resultC chan interface{} } // Get returns an existing instance of object. If it is not yet created, calls `constructor`, stores the // result for future calls and return it func Get(object interface{}, constructor func() interface{}) interface{} { e := &entry{ constructor: constructor, object: object, resultC: make(chan interface{}), } getOrCreateC <- e return <-e.resultC } func init() { go func() { for { e := <-getOrCreateC name := reflect.TypeOf(e.object).String() name = strings.TrimPrefix(name, "*") v, created := instances[name] if !created { v = e.constructor() log.Trace("Created new singleton", "object", name, "instance", v) instances[name] = v } e.resultC <- v } }() }