package fs import ( "bytes" "sync" "github.com/puzpuzpuz/xsync/v3" ) type memStorage interface { Delete(key string) (*memFile, bool) Store(key string, value *memFile) (*memFile, bool) Load(key string) (value *memFile, ok bool) LoadAndCopy(key string) (value *memFile, ok bool) Has(key string) bool Range(f func(key string, value *memFile) bool) } type mapOfStorage struct { lock *xsync.RBMutex files *xsync.MapOf[string, *memFile] } func newMapOfStorage() memStorage { m := &mapOfStorage{ lock: xsync.NewRBMutex(), files: xsync.NewMapOf[string, *memFile](), } return m } func (m *mapOfStorage) Delete(key string) (*memFile, bool) { m.lock.Lock() defer m.lock.Unlock() return m.files.LoadAndDelete(key) } func (m *mapOfStorage) Store(key string, value *memFile) (*memFile, bool) { m.lock.Lock() defer m.lock.Unlock() return m.files.LoadAndStore(key, value) } func (m *mapOfStorage) Load(key string) (*memFile, bool) { token := m.lock.RLock() defer m.lock.RUnlock(token) return m.files.Load(key) } func (m *mapOfStorage) LoadAndCopy(key string) (*memFile, bool) { token := m.lock.RLock() defer m.lock.RUnlock(token) v, ok := m.files.Load(key) if !ok { return nil, false } f := &memFile{ memFileInfo: memFileInfo{ name: v.name, size: v.size, dir: v.dir, lastMod: v.lastMod, linkTo: v.linkTo, }, r: nil, } if v.data != nil { f.data = bytes.NewBuffer(v.data.Bytes()) } return f, true } func (m *mapOfStorage) Has(key string) bool { token := m.lock.RLock() defer m.lock.RUnlock(token) _, ok := m.files.Load(key) return ok } func (m *mapOfStorage) Range(f func(key string, value *memFile) bool) { token := m.lock.RLock() defer m.lock.RUnlock(token) m.files.Range(f) } type mapStorage struct { lock sync.RWMutex files map[string]*memFile } func newMapStorage() memStorage { m := &mapStorage{ files: map[string]*memFile{}, } return m } func (m *mapStorage) Delete(key string) (*memFile, bool) { m.lock.Lock() defer m.lock.Unlock() v, ok := m.files[key] delete(m.files, key) return v, ok } func (m *mapStorage) Store(key string, value *memFile) (*memFile, bool) { m.lock.Lock() defer m.lock.Unlock() v, ok := m.files[key] m.files[key] = value return v, ok } func (m *mapStorage) Load(key string) (*memFile, bool) { m.lock.RLock() defer m.lock.RUnlock() v, ok := m.files[key] return v, ok } func (m *mapStorage) LoadAndCopy(key string) (*memFile, bool) { m.lock.RLock() defer m.lock.RUnlock() v, ok := m.files[key] if !ok { return nil, false } f := &memFile{ memFileInfo: memFileInfo{ name: v.name, size: v.size, dir: v.dir, lastMod: v.lastMod, linkTo: v.linkTo, }, r: nil, } if v.data != nil { f.data = bytes.NewBuffer(v.data.Bytes()) } return f, true } func (m *mapStorage) Has(key string) bool { m.lock.RLock() defer m.lock.RUnlock() _, ok := m.files[key] return ok } func (m *mapStorage) Range(f func(key string, value *memFile) bool) { m.lock.RLock() defer m.lock.RUnlock() for k, v := range m.files { if !f(k, v) { break } } }