Skip to content

1.0.3

@lhoward lhoward tagged this 19 Jul 07:44
The multishot recvmsg path handed buffer slots back to the ring by
convention: a `defer { Task { reprovideAndSubmit(id:) } }` inside the
buffer-pointer closure. Nothing prevented touching a slot after it was
reprovided, reproviding it twice, or forgetting to reprovide it.

Introduce ProvidedBuffer<U>, a ~Copyable handle that makes the contract
compiler-checked:

- ~Copyable: exactly one owner, so a slot cannot be reprovided twice.
- borrowing withUnsafeRawBufferPointer: payload access is scoped, so the
  slot cannot be used after ownership ends.
- deinit: the slot is reprovided (RAII) when the handle leaves scope, so a
  forgotten reprovide cannot leak it. This is the same fire-and-forget hop
  onto the ring actor the previous defer performed.

MessageHolder.receive now borrows a slot, copies the payload out, and lets
scope exit return it — no defer bookkeeping.

Adds ProvidedBufferTests, which sends more datagrams than the slot pool
holds so slots must be recycled, proving copy-out-then-reprovide preserves
every payload across reuse.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01Pw4S9tnBX48BK8UppcfmFH
Assets 2
Loading