github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/data/shm/shmi_darwin.go (about)

     1  // +build darwin,cgo
     2  
     3  package shm
     4  
     5  /*
     6  #include <sys/mman.h>
     7  #include <sys/types.h>
     8  #include <sys/stat.h>
     9  #include <fcntl.h>
    10  #include <stdio.h>
    11  #include <unistd.h>
    12  #include <sys/errno.h>
    13  
    14  int _create(const char* name, int size, int flag) {
    15  	mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP;
    16  
    17  	int fd = shm_open(name, flag, mode);
    18  	if (fd < 0) {
    19  		return -1;
    20  	}
    21  
    22  	struct stat mapstat;
    23  	int ret = fstat(fd, &mapstat);
    24  	if (ret != -1 && mapstat.st_size == 0) {
    25  		if (ftruncate(fd, size) != 0) {
    26  			close(fd);
    27  			return -2;
    28  		}
    29  	} else if (ret == -1) {
    30  		close(fd);
    31  		return -3;
    32  	}
    33  
    34  	return fd;
    35  }
    36  
    37  int Create(const char* name, int size) {
    38  	int flag = O_RDWR | O_CREAT;
    39  	return _create(name, size, flag);
    40  }
    41  
    42  int Open(const char* name, int size) {
    43  	int flag = O_RDWR;
    44  	return _create(name, size, flag);
    45  }
    46  
    47  void* Map(int fd, int size) {
    48  	void* p = mmap(
    49  		NULL, size,
    50  		PROT_READ | PROT_WRITE,
    51  		MAP_SHARED, fd, 0);
    52  	if (p == MAP_FAILED) {
    53  		return NULL;
    54  	}
    55  	return p;
    56  }
    57  
    58  void Close(int fd, void* p, int size) {
    59  	if (p != NULL) {
    60  		munmap(p, size);
    61  	}
    62  	if (fd != 0) {
    63  		close(fd);
    64  	}
    65  }
    66  
    67  void Delete(const char* name) {
    68  	shm_unlink(name);
    69  }
    70  */
    71  import "C"
    72  
    73  import (
    74  	"fmt"
    75  	"io"
    76  	"unsafe"
    77  )
    78  
    79  type sharedMemory struct {
    80  	name   string
    81  	fd     C.int
    82  	v      unsafe.Pointer
    83  	size   int32
    84  	parent bool
    85  }
    86  
    87  // create shared memory. return sharedMemory object.
    88  // name should not be more than 31 bytes.
    89  func create(name string, size int32) (*sharedMemory, error) {
    90  	name = "/" + name
    91  
    92  	fd := C.Create(C.CString(name), C.int(size))
    93  	if fd < 0 {
    94  		return nil, fmt.Errorf("create")
    95  	}
    96  
    97  	v := C.Map(fd, C.int(size))
    98  	if v == nil {
    99  		C.Close(fd, nil, C.int(size))
   100  		C.Delete(C.CString(name))
   101  	}
   102  
   103  	return &sharedMemory{name, fd, v, size, true}, nil
   104  }
   105  
   106  // open shared memory. return sharedMemory object.
   107  // name should not be more than 31 bytes.
   108  func open(name string, size int32) (*sharedMemory, error) {
   109  	name = "/" + name
   110  
   111  	fd := C.Open(C.CString(name), C.int(size))
   112  	if fd < 0 {
   113  		return nil, fmt.Errorf("open")
   114  	}
   115  
   116  	v := C.Map(fd, C.int(size))
   117  	if v == nil {
   118  		C.Close(fd, nil, C.int(size))
   119  		C.Delete(C.CString(name))
   120  	}
   121  
   122  	return &sharedMemory{name, fd, v, size, false}, nil
   123  }
   124  
   125  func (o *sharedMemory) close() error {
   126  	if o.v != nil {
   127  		C.Close(o.fd, o.v, C.int(o.size))
   128  		o.v = nil
   129  	}
   130  	if o.parent {
   131  		C.Delete(C.CString(o.name))
   132  	}
   133  	return nil
   134  }
   135  
   136  // read shared memory. return read size.
   137  func (o *sharedMemory) readAt(p []byte, off int64) (n int, err error) {
   138  	if off >= int64(o.size) {
   139  		return 0, io.EOF
   140  	}
   141  	if max := int64(o.size) - off; int64(len(p)) > max {
   142  		p = p[:max]
   143  	}
   144  	return f.BytesFromPtr(uintptr(o.v), p, off, o.size), nil
   145  }
   146  
   147  // write shared memory. return write size.
   148  func (o *sharedMemory) writeAt(p []byte, off int64) (n int, err error) {
   149  	if off >= int64(o.size) {
   150  		return 0, io.EOF
   151  	}
   152  	if max := int64(o.size) - off; int64(len(p)) > max {
   153  		p = p[:max]
   154  	}
   155  	return f.BytesToPtr(p, uintptr(o.v), off, o.size), nil
   156  }