Documentation Index
Fetch the complete documentation index at: https://mine-27913f41.mintlify.app/llms.txt
Use this file to discover all available pages before exploring further.
SharedRegion
SharedRegion is the central type in Zinc. It represents a handle to a mapped shared memory segment. Every language adapter wraps this concept in its native type system: a class in Python, Go, Java, and C#, a struct in Rust, a header-only class in C++.
A region is created by one process and opened by others. The creator’s handle carries ownership privileges. Openers get read/write access to the data area. This isn’t about security — it’s about lifecycle: only the creator may unlink the segment from the system.
Memory layout
Every mapped region starts with a 64-byte header — exactly one cache line on modern x86 and ARM. The header stores library metadata: a magic number for corruption detection, a version field for forward compatibility, a reference count, the creator’s PID, and the notification sequence counter.capacity bytes.
Naming
Each shared region has a name, chosen by the creator, that serves as its identifier on the system. Other processes use this name to open the region. Names must be non-empty and contain only ASCII alphanumeric characters, underscores, and hyphens. The pattern is[a-zA-Z0-9_-]+. Spaces, dots, slashes, and other special characters are rejected at the API level before any system call is made. This validation is identical across all adapters since it happens in the Rust core.
On Linux and macOS, the name is prefixed with /zinc_ internally when passed to shm_open. So a region named my-data becomes a POSIX shared memory object named /zinc_my-data. The prefix avoids collisions with other shared memory users on the system.
Ownership and lifecycle
The lifecycle of a shared region follows these rules:-
A process calls
createto establish a new region. The region is backed byshm_openwithO_CREAT | O_EXCL, which fails atomically if a region with the same name already exists. -
Other processes call
opento attach to the existing region.openincrements the atomic reference count stored in the header. - Any process can read and write the data area. There is no access control beyond file permissions on the shared memory object.
-
When a process is done, it calls
close(or drops the handle in languages with destructors). This decrements the reference count. - When the creator’s handle is closed and the reference count reaches zero, the region is automatically unlinked. The memory is freed once all mapped copies are unmapped.
- If an opener closes before the creator, the region stays alive. The creator retains ownership.
- If the creator crashes or forgets to unlink, the region persists in the system. Clean up stale segments by unlinking the name and creating a new one.
The 8 C functions
All language adapters call the same C ABI surface. Every function takes or returns opaque handles and primitive types only.| Function | Purpose |
|---|---|
zinc_create | Create a region. Returns handle, caller owns it. |
zinc_open | Open an existing region by name. Returns handle. |
zinc_ptr | Get raw pointer to the data area (first byte after header). |
zinc_capacity | Get usable size in bytes. |
zinc_close | Close handle. Decrements ref count. May trigger unlink. |
zinc_notify | Signal all waiters that data has changed. |
zinc_wait | Block until notified or timeout. |
zinc_version | Get library version for compatibility checks. |
Zero-copy guarantee
Zinc provides one zero-copy guarantee and one caveat. The guarantee: when you callzinc_ptr (or the adapter method that wraps it, such as as_buffer(), Bytes(), or buffer()), the returned pointer or buffer view points directly into the mapped memory. No copying occurs. A write through one adapter is immediately visible to all other adapters mapping the same region.
The caveat: Zinc does not provide built-in data structure serialization. If you write a Rust struct to shared memory and read it from Python, you must ensure the memory layout matches. For primitive arrays and flat structs, this is straightforward. For complex nested types, you need a wire format such as FlatBuffers or Cap’n Proto that can operate on shared memory directly.
