github.com/leslie-fei/fastcache@v0.0.0-20240520092641-b7a9eb05711f/shm/shm_windows.go (about)

     1  package shm
     2  
     3  import (
     4  	"syscall"
     5  	"unsafe"
     6  )
     7  
     8  var (
     9  	kernel32            = syscall.NewLazyDLL("kernel32.dll")
    10  	procOpenFileMapping = kernel32.NewProc("OpenFileMappingW")
    11  )
    12  
    13  func openFileMapping(dwDesiredAccess uint32, bInheritHandle uint32, lpName *uint16) (syscall.Handle, error) {
    14  	param1 := uintptr(dwDesiredAccess)
    15  	param2 := uintptr(bInheritHandle)
    16  	param3 := uintptr(unsafe.Pointer(lpName))
    17  	ret, _, err := procOpenFileMapping.Call(param1, param2, param3)
    18  	if 0 == err.(syscall.Errno) {
    19  		err = nil
    20  	}
    21  	return syscall.Handle(ret), err
    22  }
    23  
    24  func NewMemory(key string, bytes uint64, createIfNotExists bool) *Memory {
    25  	return &Memory{
    26  		createIfNotExists: createIfNotExists,
    27  		shmkey:            key,
    28  		bytes:             bytes,
    29  	}
    30  }
    31  
    32  func (m *Memory) Attach() error {
    33  	if m.basep != 0 {
    34  		return nil
    35  	}
    36  
    37  	if 0 == m.shmid {
    38  		name, err := syscall.UTF16PtrFromString(m.shmkey)
    39  		if nil != err {
    40  			return err
    41  		}
    42  
    43  		// open file mapping
    44  		handle, err := openFileMapping(syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, name)
    45  		if nil != err && m.createIfNotExists {
    46  			// create file mapping if not exists
    47  			sizehi := uint32(m.bytes >> 32)
    48  			sizelo := uint32(m.bytes) & 0xffffffff
    49  			handle, err = syscall.CreateFileMapping(syscall.InvalidHandle, nil, syscall.PAGE_READWRITE, sizehi, sizelo, name)
    50  		}
    51  
    52  		if nil != err {
    53  			return err
    54  		}
    55  
    56  		m.shmid = uint64(handle)
    57  	}
    58  
    59  	// MapViewOfFile
    60  	basep, err := syscall.MapViewOfFile(syscall.Handle(m.shmid), syscall.FILE_MAP_READ|syscall.FILE_MAP_WRITE, 0, 0, uintptr(m.bytes))
    61  	if err != nil {
    62  		return err
    63  	}
    64  
    65  	// save pointer
    66  	m.basep = uint64(basep)
    67  	return nil
    68  }
    69  
    70  func (m *Memory) Detach() (err error) {
    71  	if m.basep != 0 {
    72  		err = syscall.UnmapViewOfFile(uintptr(m.basep))
    73  		m.basep = 0
    74  	}
    75  
    76  	return
    77  }