Interface BufferRef

All Known Implementing Classes:
BufferRefImpl

public interface BufferRef
A reference-counted handle to a shared off-heap memory segment.

This is the fundamental "Atom" of the transport's buffer system. It wraps a MemorySegment with explicit ownership semantics via reference counting, designed for efficient pooling and reuse.

Reference Counting

BufferRef uses explicit reference counting for memory management:

  • Acquire: When obtained from pool, refCount starts at 1
  • Retain: Call retain() to increment count when sharing
  • Release: Call release() when done; auto-returns to pool at 0

Usage Pattern

BufferRef buf = pool.acquire();
try {
    // Write data to segment
    buf.segment().setAtIndex(ValueLayout.JAVA_BYTE, 0, data);
    buf.length(dataLen);

    // If sharing with another thread:
    buf.retain();
    executor.submit(() -> {
        try {
            process(buf);
        } finally {
            buf.release();
        }
    });
} finally {
    buf.release(); // Returns to pool when refCount hits 0
}

Structure of Arrays (SoA) Pattern

The poolIndex() method supports SoA patterns where metadata (timestamps, flags, etc.) is stored in separate primitive arrays indexed by pool index, avoiding object header overhead.

Thread Safety

Reference counting operations (retain(), release()) are thread-safe using lock-free CAS operations. The underlying segment access is not synchronized; callers must ensure proper happens-before relationships.

See Also:
  • Method Summary

    Modifier and Type
    Method
    Description
    long
    Returns the raw native address of the segment.
    int
    Returns the current length of valid data in the buffer.
    void
    length(int newLength)
    Sets the length of valid data in the buffer.
    int
    Returns the unique index of this buffer in the global pool.
    short
    Returns the io_uring registration ID if registered.
    void
    Decrements the reference count.
    void
    Increments the reference count.
    Returns the underlying FFM MemorySegment.
  • Method Details

    • segment

      MemorySegment segment()
      Returns the underlying FFM MemorySegment.

      Warning: Accessing this segment after release() has reduced the refCount to 0 is undefined behavior. The segment may be reused by another thread or the underlying memory may be invalidated.

      Returns:
      the memory segment backing this buffer
    • address

      long address()
      Returns the raw native address of the segment.

      This is cached to avoid JNI/FFM overhead on hot paths. Useful for direct native library integration.

      Returns:
      the native memory address
    • poolIndex

      int poolIndex()
      Returns the unique index of this buffer in the global pool.

      This enables "Structure of Arrays" (SoA) patterns where metadata (refCounts, timestamps, operation tokens) is stored in separate primitive arrays indexed by this ID, rather than in object fields.

      Returns:
      the buffer's index in its pool (0-based)
    • registrationId

      short registrationId()
      Returns the io_uring registration ID if registered.

      For io_uring backends, this is the buffer index used with IORING_OP_READ_FIXED and IORING_OP_WRITE_FIXED.

      Returns:
      the registration ID, or -1 if not registered
    • length

      int length()
      Returns the current length of valid data in the buffer.

      This represents the actual payload size (e.g., packet length), not the buffer capacity.

      Returns:
      the valid data length in bytes
    • length

      void length(int newLength)
      Sets the length of valid data in the buffer.
      Parameters:
      newLength - the new data length in bytes
    • retain

      void retain()
      Increments the reference count.

      Must be called before sharing the buffer with another thread or holding it asynchronously past the current scope.

      Throws:
      IllegalStateException - if refCount is already 0 (buffer released)
    • release

      void release()
      Decrements the reference count.

      If the count reaches 0, the buffer is automatically returned to its pool for reuse. After the final release, the buffer must not be accessed.

      Throws:
      IllegalStateException - if refCount is already 0 (double-release)