Skip to content

Commit a060064

Browse files
authored
Merge pull request #160 from oschwald/greg/windows-mmap-update
Modernize Windows mmap code
2 parents 5f9867c + f9c7597 commit a060064

File tree

1 file changed

+55
-38
lines changed

1 file changed

+55
-38
lines changed

mmap_windows.go

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

4039
"golang.org/x/sys/windows"
4140
)
4241

43-
type memoryMap []byte
44-
4542
// Windows
4643
var (
4744
handleLock sync.Mutex
4845
handleMap = map[uintptr]windows.Handle{}
4946
)
5047

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)
48+
// mmap maps a file into memory and returns a byte slice.
49+
func mmap(fd int, length int) ([]byte, error) {
50+
// Create a file mapping
51+
handle, err := windows.CreateFileMapping(
52+
windows.Handle(fd),
53+
nil,
54+
windows.PAGE_READONLY,
55+
0,
56+
uint32(length),
57+
nil,
58+
)
59+
if err != nil {
60+
return nil, os.NewSyscallError("CreateFileMapping", err)
5661
}
5762

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)
63+
// Map the file into memory
64+
addr, err := windows.MapViewOfFile(
65+
handle,
66+
windows.FILE_MAP_READ,
67+
0,
68+
0,
69+
uintptr(length),
70+
)
71+
if err != nil {
72+
windows.CloseHandle(handle)
73+
return nil, os.NewSyscallError("MapViewOfFile", err)
6274
}
75+
76+
// Store the handle in the map
6377
handleLock.Lock()
64-
handleMap[addr] = h
78+
handleMap[addr] = handle
6579
handleLock.Unlock()
6680

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))
81+
data := unsafe.Slice((*byte)(unsafe.Pointer(addr)), length)
82+
return data, nil
7883
}
7984

80-
func flush(addr, len uintptr) error {
81-
errno := windows.FlushViewOfFile(addr, len)
82-
return os.NewSyscallError("FlushViewOfFile", errno)
85+
// flush ensures changes to a memory-mapped region are written to disk.
86+
func flush(addr, length uintptr) error {
87+
err := windows.FlushViewOfFile(addr, length)
88+
if err != nil {
89+
return os.NewSyscallError("FlushViewOfFile", err)
90+
}
91+
return nil
8392
}
8493

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)
94+
// munmap unmaps a memory-mapped file and releases associated resources.
95+
func munmap(b []byte) error {
96+
// Convert slice to base address and length
97+
data := unsafe.SliceData(b)
98+
addr := uintptr(unsafe.Pointer(data))
99+
length := uintptr(len(b))
91100

92-
flush(addr, length)
93-
err = windows.UnmapViewOfFile(addr)
94-
if err != nil {
101+
// Flush the memory region
102+
if err := flush(addr, length); err != nil {
95103
return err
96104
}
97105

106+
// Unmap the memory
107+
if err := windows.UnmapViewOfFile(addr); err != nil {
108+
return os.NewSyscallError("UnmapViewOfFile", err)
109+
}
110+
111+
// Remove the handle from the map and close it
98112
handleLock.Lock()
99113
defer handleLock.Unlock()
114+
100115
handle, ok := handleMap[addr]
101116
if !ok {
102117
// should be impossible; we would've errored above
103118
return errors.New("unknown base address")
104119
}
105120
delete(handleMap, addr)
106121

107-
e := windows.CloseHandle(windows.Handle(handle))
108-
return os.NewSyscallError("CloseHandle", e)
122+
if err := windows.CloseHandle(handle); err != nil {
123+
return os.NewSyscallError("CloseHandle", err)
124+
}
125+
return nil
109126
}

0 commit comments

Comments
 (0)