zhangmeng
2019-08-26 a0123f163eddcea3e6b9f9d36f1f3fb3aa2c835a
提交 | 用户 | age
3bd1f2 1 // Copyright 2016 Tom Thorogood. All rights reserved.
Z 2 // Use of this source code is governed by a
3 // Modified BSD License license that can be found in
4 // the LICENSE file.
5
6 package shm
7
8 import (
9     "sync/atomic"
10     "unsafe"
11
a0123f 12     "golang.org/x/sys/unix"
3bd1f2 13 )
Z 14
15 func OpenSimplex(name string) (*ReadWriteCloser, error) {
a0123f 16     file, err := Open(name, unix.O_RDWR, 0)
3bd1f2 17     if err != nil {
Z 18         return nil, err
19     }
20
21     defer file.Close()
22
23     data, err := unix.Mmap(int(file.Fd()), 0, sharedHeaderSize, unix.PROT_READ, unix.MAP_SHARED)
24     if err != nil {
25         return nil, err
26     }
27
28     shared := (*sharedMem)(unsafe.Pointer(&data[0]))
29
30     if atomic.LoadUint32((*uint32)(&shared.Version)) != version {
31         return nil, ErrInvalidSharedMemory
32     }
33
34     blockCount, blockSize := uint64(shared.BlockCount), uint64(shared.BlockSize)
35
36     if err = unix.Munmap(data); err != nil {
37         return nil, err
38     }
39
40     size := sharedHeaderSize + (blockHeaderSize+blockSize)*blockCount
41
42     data, err = unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
43     if err != nil {
44         return nil, err
45     }
46
47     shared = (*sharedMem)(unsafe.Pointer(&data[0]))
48     return &ReadWriteCloser{
49         name: name,
50
51         data:          data,
52         readShared:    shared,
53         writeShared:   shared,
54         size:          size,
55         fullBlockSize: blockHeaderSize + blockSize,
56
57         Flags: (*[len(shared.Flags)]uint32)(unsafe.Pointer(&shared.Flags[0])),
58     }, nil
59 }
60
61 func OpenDuplex(name string) (*ReadWriteCloser, error) {
a0123f 62     file, err := Open(name, unix.O_RDWR, 0)
3bd1f2 63     if err != nil {
Z 64         return nil, err
65     }
66
67     defer file.Close()
68
69     data, err := unix.Mmap(int(file.Fd()), 0, sharedHeaderSize, unix.PROT_READ, unix.MAP_SHARED)
70     if err != nil {
71         return nil, err
72     }
73
74     shared := (*sharedMem)(unsafe.Pointer(&data[0]))
75
76     if atomic.LoadUint32((*uint32)(&shared.Version)) != version {
77         return nil, ErrInvalidSharedMemory
78     }
79
80     blockCount, blockSize := uint64(shared.BlockCount), uint64(shared.BlockSize)
81
82     if err = unix.Munmap(data); err != nil {
83         return nil, err
84     }
85
86     sharedSize := sharedHeaderSize + (blockHeaderSize+blockSize)*blockCount
87     size := 2 * sharedSize
88
89     data, err = unix.Mmap(int(file.Fd()), 0, int(size), unix.PROT_READ|unix.PROT_WRITE, unix.MAP_SHARED)
90     if err != nil {
91         return nil, err
92     }
93
94     writeShared := (*sharedMem)(unsafe.Pointer(&data[0]))
95     return &ReadWriteCloser{
96         name: name,
97
98         data:          data,
99         readShared:    (*sharedMem)(unsafe.Pointer(&data[sharedSize])),
100         writeShared:   writeShared,
101         size:          size,
102         fullBlockSize: blockHeaderSize + blockSize,
103
104         Flags: (*[len(writeShared.Flags)]uint32)(unsafe.Pointer(&writeShared.Flags[0])),
105     }, nil
106 }