github.com/leslie-fei/fastcache@v0.0.0-20240520092641-b7a9eb05711f/mmap/mmap.go (about) 1 package mmap 2 3 import ( 4 "fmt" 5 "os" 6 "reflect" 7 "unsafe" 8 9 "github.com/edsrzf/mmap-go" 10 ) 11 12 type Memory struct { 13 filepath string 14 bytes uint64 15 file *os.File 16 mmap mmap.MMap 17 basep unsafe.Pointer 18 } 19 20 func NewMemory(filepath string, bytes uint64) *Memory { 21 return &Memory{filepath: filepath, bytes: bytes} 22 } 23 24 func (m *Memory) Attach() (err error) { 25 if nil == m.file { 26 if m.file, err = os.OpenFile(m.filepath, os.O_RDWR|os.O_CREATE, 0666); nil != err { 27 return err 28 } 29 30 if err = m.file.Truncate(int64(m.bytes)); nil != err { 31 m.file.Close() 32 m.file = nil 33 return err 34 } 35 36 if m.mmap, err = mmap.Map(m.file, mmap.RDWR, 0); nil != err { 37 m.file.Close() 38 m.file = nil 39 return err 40 } 41 42 sh := (*reflect.SliceHeader)(unsafe.Pointer(&m.mmap)) 43 m.basep = unsafe.Pointer(sh.Data) 44 } 45 return 46 } 47 48 func (m *Memory) Detach() error { 49 if nil != m.mmap { 50 if err := m.mmap.Unmap(); nil != err { 51 return err 52 } 53 m.mmap = nil 54 m.basep = unsafe.Pointer(nil) 55 } 56 57 if nil != m.file { 58 if err := m.file.Close(); nil != err { 59 return err 60 } 61 m.file = nil 62 } 63 return nil 64 } 65 66 func (m *Memory) Ptr() unsafe.Pointer { 67 return m.basep 68 } 69 70 func (m *Memory) Size() uint64 { 71 return m.bytes 72 } 73 74 func (m *Memory) PtrOffset(offset uint64) unsafe.Pointer { 75 if offset >= m.bytes { 76 panic(fmt.Errorf("offset overflow: %d > %d", offset, m.bytes)) 77 } 78 return unsafe.Pointer(uintptr(m.basep) + uintptr(offset)) 79 } 80 81 func (m *Memory) Travel(skipOffset uint64, fn func(ptr unsafe.Pointer, size uint64) uint64) { 82 for skipOffset < m.bytes { 83 if advanceBytes := fn(m.PtrOffset(skipOffset), m.bytes-skipOffset); advanceBytes > 0 { 84 skipOffset += advanceBytes 85 continue 86 } 87 break 88 } 89 }