Skip to content

Commit adcf840

Browse files
committed
Modernize Windows mmap code
1 parent 5f9867c commit adcf840

File tree

1 file changed

+58
-37
lines changed

1 file changed

+58
-37
lines changed

mmap_windows.go

Lines changed: 58 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,6 @@ package maxminddb
3333
import (
3434
"errors"
3535
"os"
36-
"reflect"
3736
"sync"
3837
"unsafe"
3938

@@ -48,62 +47,84 @@ var (
4847
handleMap = map[uintptr]windows.Handle{}
4948
)
5049

51-
func mmap(fd int, length int) (data []byte, err error) {
52-
h, errno := windows.CreateFileMapping(windows.Handle(fd), nil,
53-
uint32(windows.PAGE_READONLY), 0, uint32(length), nil)
54-
if h == 0 {
55-
return nil, os.NewSyscallError("CreateFileMapping", errno)
50+
// mmap maps a file into memory and returns a memoryMap.
51+
func mmap(fd int, length int) ([]byte, error) {
52+
// Create a file mapping
53+
handle, err := windows.CreateFileMapping(
54+
windows.Handle(fd),
55+
nil,
56+
windows.PAGE_READONLY,
57+
0,
58+
uint32(length),
59+
nil,
60+
)
61+
if err != nil {
62+
return nil, os.NewSyscallError("CreateFileMapping", err)
5663
}
57-
58-
addr, errno := windows.MapViewOfFile(h, uint32(windows.FILE_MAP_READ), 0,
59-
0, uintptr(length))
60-
if addr == 0 {
61-
return nil, os.NewSyscallError("MapViewOfFile", errno)
64+
// Ensure the handle is closed if mapping fails
65+
defer windows.CloseHandle(handle)
66+
67+
// Map the file into memory
68+
addr, err := windows.MapViewOfFile(
69+
handle,
70+
windows.FILE_MAP_READ,
71+
0,
72+
0,
73+
uintptr(length),
74+
)
75+
if err != nil {
76+
return nil, os.NewSyscallError("MapViewOfFile", err)
6277
}
78+
79+
// Store the handle in the map
6380
handleLock.Lock()
64-
handleMap[addr] = h
81+
handleMap[addr] = handle
6582
handleLock.Unlock()
6683

67-
m := memoryMap{}
68-
dh := m.header()
69-
dh.Data = addr
70-
dh.Len = length
71-
dh.Cap = dh.Len
72-
73-
return m, nil
74-
}
75-
76-
func (m *memoryMap) header() *reflect.SliceHeader {
77-
return (*reflect.SliceHeader)(unsafe.Pointer(m))
84+
// Convert addr to a slice without triggering warnings
85+
data := unsafe.Slice((*byte)(unsafe.Pointer(addr)), length)
86+
return data, nil
7887
}
7988

80-
func flush(addr, len uintptr) error {
81-
errno := windows.FlushViewOfFile(addr, len)
82-
return os.NewSyscallError("FlushViewOfFile", errno)
89+
// flush ensures changes to a memory-mapped region are written to disk.
90+
func flush(addr, length uintptr) error {
91+
err := windows.FlushViewOfFile(addr, length)
92+
if err != nil {
93+
return os.NewSyscallError("FlushViewOfFile", err)
94+
}
95+
return nil
8396
}
8497

85-
func munmap(b []byte) (err error) {
86-
m := memoryMap(b)
87-
dh := m.header()
88-
89-
addr := dh.Data
90-
length := uintptr(dh.Len)
98+
// munmap unmaps a memory-mapped file and releases associated resources.
99+
func munmap(b []byte) error {
100+
// Convert slice to base address and length
101+
data := unsafe.SliceData(b)
102+
addr := uintptr(unsafe.Pointer(data))
103+
length := uintptr(len(b))
91104

92-
flush(addr, length)
93-
err = windows.UnmapViewOfFile(addr)
94-
if err != nil {
105+
// Flush the memory region
106+
if err := flush(addr, length); err != nil {
95107
return err
96108
}
97109

110+
// Unmap the memory
111+
if err := windows.UnmapViewOfFile(addr); err != nil {
112+
return os.NewSyscallError("UnmapViewOfFile", err)
113+
}
114+
115+
// Remove the handle from the map and close it
98116
handleLock.Lock()
99117
defer handleLock.Unlock()
118+
100119
handle, ok := handleMap[addr]
101120
if !ok {
102121
// should be impossible; we would've errored above
103122
return errors.New("unknown base address")
104123
}
105124
delete(handleMap, addr)
106125

107-
e := windows.CloseHandle(windows.Handle(handle))
108-
return os.NewSyscallError("CloseHandle", e)
126+
if err := windows.CloseHandle(handle); err != nil {
127+
return os.NewSyscallError("CloseHandle", err)
128+
}
129+
return nil
109130
}

0 commit comments

Comments
 (0)