Increment 2: wires the host-call machinery into the running FFI thread so a
host answer (delivered from any thread) resolves the chronos Future an awaiting
handler is blocked on.
- FFICompletionQueue (ffi_host.nim): a GC-free intrusive queue. host_complete
pushes c_malloc'd nodes from any thread; the FFI thread drains, copies the
payload into GC memory, completes the future by token, and frees the node.
- FFIContext gains hostRegistry / pendingTable / completionQueue, init'd and
deinit'd alongside the event registry.
- completeHostCall parks the answer and fires the EXISTING reqSignal — no second
ThreadSignalPtr needed; the loop drains completions every iteration, on the
loop thread (chronos single-thread invariant).
- On shutdown the loop failAllPendings first, so a handler awaiting a host
answer that never arrives can't hang the allFutures(pending) drain.
4 new queue unit tests (10 total) pass under orc+refc; the 19 ffi_context
integration tests stay green.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
First increment of typed host callbacks (roadmap #1): the data-structure
layer, independent of the FFI thread and the macro so it can be unit-tested
in isolation.
- FFIHostRegistry: wire-name -> (host fn ptr, userData). A missing entry is a
normal outcome (the imported proc errors), never a crash — never-crash
policy. nil fn unregisters.
- FFIPendingTable: monotonic token -> the chronos Future an awaiting
{.ffiHost.} proc is blocked on. completePending drops unknown/double
completions; failAllPending errors every outstanding future on teardown so
no awaiting handler is abandoned.
Both lock-guarded so a host thread and the FFI thread can touch them
concurrently; futures are only ever completed on the FFI thread. 6 unit tests
pass under orc and refc.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>