Documentation
¶
Overview ¶
Package shmring implements a fixed-capacity, single-producer/ single-consumer byte ring buffer on top of github.com/hidez8891/shm.
A ring buffer is created by one side (the producer) with CreateShm and opened by the other side (the consumer) with OpenShm, naming the same OS shared-memory segment. Bytes written by the Writer become visible to the Reader in FIFO order, wrapping around the underlying storage as needed.
The storage the ring buffer runs on is pluggable (see the backend package): CreateShm/OpenShm use OS shared memory for cross-process use, while NewWriter/NewReader accept any backend.Storage, which is what makes it possible to run the exact same algorithm over a plain in-process byte slice (backend.MemStorage, handy for tests) or over a future backend for a platform or transport hidez8891/shm doesn't cover yet.
Concurrency model ¶
A ring buffer has exactly one Writer and one Reader. Each must only be used from a single goroutine at a time (the Writer's goroutine may differ from the Reader's goroutine, and in the cross-process case they're typically different processes entirely). Calling Write concurrently from two goroutines, or Read concurrently from two goroutines, is not supported.
The head/tail coordination between the Writer and the Reader relies on plain, naturally aligned 64-bit loads and stores to the shared region rather than compiler/hardware-level atomics (the underlying shm library only exposes ReadAt/WriteAt, not a raw pointer into the mapping). This is the same assumption classic SPSC ring buffers over shared memory (e.g. Linux kfifo) make, and holds on every architecture Go currently targets, but it is weaker than the guarantees sync/atomic gives you within a single process. Do not repurpose the Writer/Reader split for anything other than the SPSC pattern it was designed for.
CreateShm/OpenShm need GOOS=android excluded even though it inherits the "linux" build tag: they call into backend.CreateShm/OpenShm, which are built on hidez8891/shm's POSIX shm_open/shm_unlink -- and Android's bionic libc doesn't implement those (mmap/munmap only). See shm_android.go for Android's real backend (ASharedMemory).
Index ¶
Constants ¶
This section is empty.
Variables ¶
var ( // ErrClosed is returned by Write/Read operations performed after the // Writer has been closed and, for reads, once all buffered data has // been drained. ErrClosed = errors.New("shmring: ring buffer closed") // ErrInvalidCapacity is returned when a requested capacity is not a // power of two, or is not positive. ErrInvalidCapacity = errors.New("shmring: capacity must be a positive power of two") // ErrHeaderMismatch is returned by NewReader/OpenShm when the header // found in storage doesn't match what this version of shmring expects // (wrong magic, incompatible format version, or a capacity different // from the one requested). ErrHeaderMismatch = errors.New("shmring: storage header does not match expected ring buffer format") // ErrStorageTooSmall is returned when the provided storage is smaller // than headerSize+capacity. ErrStorageTooSmall = errors.New("shmring: storage is too small for the requested capacity") )
Functions ¶
This section is empty.
Types ¶
type Option ¶
type Option func(*options)
Option configures a Writer or Reader created by NewWriter, NewReader, CreateShm or OpenShm.
func WithPollInterval ¶
WithPollInterval sets the backoff range used while a blocking Write waits for free space, or a blocking Read waits for data. The wait starts at min and doubles up to max between each check of the shared head/tail counters. Smaller values reduce latency at the cost of burning more CPU while waiting.
type Reader ¶
type Reader struct {
// contains filtered or unexported fields
}
Reader is the consumer side of a ring buffer. A Reader must only be used from a single goroutine at a time.
func NewReader ¶
NewReader attaches to a ring buffer previously initialized by NewWriter on the same storage. capacity must match the value the writer used.
NewReader is the low-level entry point used by OpenShm; use it directly when running the ring buffer over a custom backend.Storage.
func OpenShm ¶
OpenShm opens a shared-memory segment created by CreateShm with the same name and capacity, and returns the Reader for it.
func (*Reader) Close ¶
Close releases the Reader's handle on the underlying storage. For OS shared memory this unmaps the segment (it does not remove it; only the creating Writer's CloseStorage does that).
func (*Reader) Read ¶
Read blocks until at least one byte is available and reads into p. It implements io.Reader, including returning io.EOF once the Writer has closed and all buffered data has been drained.
func (*Reader) ReadContext ¶
ReadContext is like Read but returns ctx.Err() if ctx is done before any data becomes available.
type Writer ¶
type Writer struct {
// contains filtered or unexported fields
}
Writer is the producer side of a ring buffer. A Writer must only be used from a single goroutine at a time.
func CreateShm ¶
CreateShm creates a new OS shared-memory segment named name, sized for the given data capacity (a positive power of two), and returns the Writer for it. The segment is removed from the OS when the Writer is closed. The consumer opens the same segment with OpenShm.
func NewWriter ¶
NewWriter initializes a fresh ring buffer header on st and returns the producer handle for it. capacity must be a positive power of two, and st must be at least headerSize+capacity bytes.
NewWriter is the low-level entry point used by CreateShm; use it directly when running the ring buffer over a custom backend.Storage (for example backend.MemStorage in tests).
func (*Writer) Close ¶
Close marks the ring buffer as closed. Any data already written remains available for the Reader to drain; once drained, the Reader's Read calls return ErrClosed. Close does not release the underlying storage — call Storage.Close (or keep using the Writer's storage via Reader) separately once both sides are done, since the Reader may still be reading.
func (*Writer) CloseStorage ¶
CloseStorage closes the underlying storage in addition to marking the ring buffer closed. For OS shared memory this unmaps the segment and, on the creating side, removes it. Call this once no other process still needs the storage.
func (*Writer) TryWrite ¶
TryWrite writes as much of p as currently fits in the ring buffer without blocking, returning the number of bytes written. It returns (0, nil) if the buffer is full, and (0, ErrClosed) if the Writer has been closed.
Source Files
¶
Directories
¶
| Path | Synopsis |
|---|---|
|
Package backend defines the storage abstraction that the ring buffer is built on top of, plus the implementations shmring ships with.
|
Package backend defines the storage abstraction that the ring buffer is built on top of, plus the implementations shmring ships with. |
|
examples
|
|
|
consumer
command
Command consumer opens a shared-memory ring buffer created by the producer example and prints every message it reads until the producer closes the ring and it drains.
|
Command consumer opens a shared-memory ring buffer created by the producer example and prints every message it reads until the producer closes the ring and it drains. |
|
producer
command
Command producer creates a shared-memory ring buffer and streams numbered messages into it.
|
Command producer creates a shared-memory ring buffer and streams numbered messages into it. |
|
web
|
|
|
devserver
command
Command devserver serves the shmring web/ directory (wasm_exec.js, shmring.js, shmring.wasm, and the example/ page) with the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy response headers that SharedArrayBuffer requires.
|
Command devserver serves the shmring web/ directory (wasm_exec.js, shmring.js, shmring.wasm, and the example/ page) with the Cross-Origin-Opener-Policy and Cross-Origin-Embedder-Policy response headers that SharedArrayBuffer requires. |
|
wasm
command
Command wasm compiles to shmring.wasm: a WebAssembly build of the shmring library exposed to JavaScript on globalThis.shmring, for use in a browser via web/shmring.js.
|
Command wasm compiles to shmring.wasm: a WebAssembly build of the shmring library exposed to JavaScript on globalThis.shmring, for use in a browser via web/shmring.js. |