Expand description
VECSXP-backed protection pool with generational keys.
A GC protection mechanism that stores protected SEXPs in a single R VECSXP (generic list), with slot management and generation tracking on the Rust side.
§Performance
Benchmarked at 10.1 ns/op for single insert+release. Zero R allocation per
insert (unlike R_PreserveObject, which allocates a CONSXP each time).
See analysis/gc-protection-benchmarks-results.md for full data.
§When to use
Use this for cross-.Call protection when:
- You have many protected objects or frequent insert/release churn
- You need any-order release (not LIFO)
- You want generational safety (stale-key detection)
For temporaries within a .Call, use ProtectScope
instead (7.4 ns/op, zero allocation, LIFO bulk cleanup).
R_PreserveObject is only appropriate for a singleton object that is
released (if ever) in LIFO order relative to other preserved objects — e.g.
this pool’s own backing VECSXP. It is not appropriate for objects held
in bulk and released in arbitrary or FIFO order: R_ReleaseObject’s O(n)
precious-list scan degrades to O(n²) on exactly that pattern (60–65× slower
than this pool at 10k objects; see
analysis/gc-protection-benchmarks-results.md). ExternalPtr roots through
this pool for that reason — a Vec<ExternalPtr> releases its roots
front-to-back, the worst case for the precious list.
§Architecture
┌─────────────────────────────────────┐
│ R side: VECSXP (GC-traced slots) │ ← one R_PreserveObject, ever
│ [SEXP][SEXP][NIL][SEXP][NIL][SEXP] │
└──────┬──────────────────────────────┘
│ slot indices
┌──────┴──────────────────────────────┐
│ Rust side: Vec<u32> generations │ ← one free list, one generation array
│ + Vec<usize> free_slots │
└─────────────────────────────────────┘No external dependencies for slot management. The generation counter per slot detects stale keys. Single free list for VECSXP slot reuse.
Structs§
- Protect
Key - Generational key for a slot in a
ProtectPool. - Protect
Pool - A VECSXP-backed pool for GC protection with generational keys.
Type Aliases§
- NoSend
Sync 🔒 - Enforces
!Send + !Sync(R API is not thread-safe).