| 提交 | 用户 | 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 | } | |