Skip to main content

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.
// Creator: owns the segment, may unlink on drop
let region = SharedRegion::create("my-segment", 65536);

// Opener: reads and writes, but cannot unlink
let region = SharedRegion::open("my-segment");

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.
Offset  Size  Field         Description
------  ----  -----         -----------
0       8     magic         Must equal 0x5A494E435F524547 ("ZINC_REG")
8       2     version       Breaking-change guard (currently 1)
10      2     flags         Reserved for future use
12      4     notify_seq    Futex/semaphore signal counter
16      8     capacity      Usable bytes after the header
24      4     ref_count     Atomic reference count
28      4     owner_pid     PID of the creating process
32      8     created_at    Unix timestamp in nanoseconds
40      8     name_hash     FNV-1a hash of the region name
48      8     ring_head     Notification ring write head
56      8     ring_tail     Notification ring read tail
The usable data area begins at byte 64 and extends for 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:
  1. A process calls create to establish a new region. The region is backed by shm_open with O_CREAT | O_EXCL, which fails atomically if a region with the same name already exists.
  2. Other processes call open to attach to the existing region. open increments the atomic reference count stored in the header.
  3. Any process can read and write the data area. There is no access control beyond file permissions on the shared memory object.
  4. When a process is done, it calls close (or drops the handle in languages with destructors). This decrements the reference count.
  5. 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.
  6. If an opener closes before the creator, the region stays alive. The creator retains ownership.
  7. 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.
FunctionPurpose
zinc_createCreate a region. Returns handle, caller owns it.
zinc_openOpen an existing region by name. Returns handle.
zinc_ptrGet raw pointer to the data area (first byte after header).
zinc_capacityGet usable size in bytes.
zinc_closeClose handle. Decrements ref count. May trigger unlink.
zinc_notifySignal all waiters that data has changed.
zinc_waitBlock until notified or timeout.
zinc_versionGet library version for compatibility checks.
Error codes follow POSIX conventions: zero means success, negative values indicate specific errors. Every adapter translates these into language-native exceptions or error types.

Zero-copy guarantee

Zinc provides one zero-copy guarantee and one caveat. The guarantee: when you call zinc_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.

Synchronization

Zinc provides a lightweight notify/wait mechanism built on an atomic sequence counter. Not a general-purpose synchronization primitive. It solves one pattern: a producer writes data, then signals consumers. For complex synchronization — multiple producers, reader-writer locks, condition variables that guard multi-field updates — reach for atomic operations on the shared data itself. The notify/wait mechanism only signals that something changed. It does not say what changed or protect against races. See the notify/wait guide for detailed usage.