diff --git a/index.go b/index.go index acdb95d..5466602 100644 --- a/index.go +++ b/index.go @@ -14,13 +14,14 @@ import ( type index struct { Files *filesMap - Infos map[string]here.Info + Infos *infosMap current here.Info once sync.Once } func (i *index) Info(p string) (here.Info, error) { - if info, ok := i.Infos[p]; ok { + info, ok := i.Infos.Load(p) + if ok { return info, nil } @@ -28,14 +29,11 @@ func (i *index) Info(p string) (here.Info, error) { if err != nil { return info, err } - i.Infos[p] = info + i.Infos.Store(p, info) return info, nil } func (i *index) Current() (here.Info, error) { - if !i.current.IsZero() { - return i.current, nil - } var err error i.once.Do(func() { i.current, err = here.Cache("", func(string) (here.Info, error) { @@ -183,7 +181,7 @@ func (i index) openDisk(pt Path) (*File, error) { func newIndex() *index { return &index{ Files: &filesMap{}, - Infos: map[string]here.Info{}, + Infos: &infosMap{}, } } diff --git a/infos_map.go b/infos_map.go new file mode 100644 index 0000000..ce3b576 --- /dev/null +++ b/infos_map.go @@ -0,0 +1,99 @@ +// Code generated by github.com/gobuffalo/mapgen. DO NOT EDIT. + +package pkger + +import ( + "sort" + "sync" + + "github.com/gobuffalo/here" +) + +// infosMap wraps sync.Map and uses the following types: +// key: string +// value: here.Info +type infosMap struct { + data *sync.Map + init sync.Once +} + +func (m *infosMap) Data() *sync.Map { + m.init.Do(func() { + if m.data == nil { + m.data = &sync.Map{} + } + }) + return m.data +} + +// Delete the key from the map +func (m *infosMap) Delete(key string) { + m.Data().Delete(key) +} + +// Load the key from the map. +// Returns here.Info or bool. +// A false return indicates either the key was not found +// or the value is not of type here.Info +func (m *infosMap) Load(key string) (here.Info, bool) { + i, ok := m.Data().Load(key) + if !ok { + return here.Info{}, false + } + s, ok := i.(here.Info) + return s, ok +} + +// LoadOrStore will return an existing key or +// store the value if not already in the map +func (m *infosMap) LoadOrStore(key string, value here.Info) (here.Info, bool) { + i, _ := m.Data().LoadOrStore(key, value) + s, ok := i.(here.Info) + return s, ok +} + +// LoadOr will return an existing key or +// run the function and store the results +func (m *infosMap) LoadOr(key string, fn func(*infosMap) (here.Info, bool)) (here.Info, bool) { + i, ok := m.Load(key) + if ok { + return i, ok + } + i, ok = fn(m) + if ok { + m.Store(key, i) + return i, ok + } + return i, false +} + +// Range over the here.Info values in the map +func (m *infosMap) Range(f func(key string, value here.Info) bool) { + m.Data().Range(func(k, v interface{}) bool { + key, ok := k.(string) + if !ok { + return false + } + value, ok := v.(here.Info) + if !ok { + return false + } + return f(key, value) + }) +} + +// Store a here.Info in the map +func (m *infosMap) Store(key string, value here.Info) { + m.Data().Store(key, value) +} + +// Keys returns a list of keys in the map +func (m *infosMap) Keys() []string { + var keys []string + m.Range(func(key string, value here.Info) bool { + keys = append(keys, key) + return true + }) + sort.Strings(keys) + return keys +}