Skip to main content

Protector

Trait Protector 

Source
pub unsafe trait Protector {
    // Required method
    fn protect(&mut self, sexp: SEXP) -> SEXP;
}
Expand description

A scope-like GC protection backend: everything it protects stays rooted until the protector drops.

Code that allocates several intermediate SEXPs can take &mut impl Protector and leave the choice of backend to its caller. There is no individual release through this trait; for that, use ProtectPool::insert and ProtectPool::release.

§Which backend

  • A temporary within one call: ProtectScope, R’s protect stack. The cheapest; its values unprotect together, in LIFO order with the rest of the stack.
  • Many values, any drop order, or owned by a struct: ProtectPool, one R list that the pool preserves. No protect-stack entry per value, and dropping it releases everything it holds whatever the order.
  • One long-lived object: Preserved, a handle, not a Protector.

There is no precious-list Protector. R_PreserveObject per value allocates a cell each time, and R_ReleaseObject scans the precious list from its head, so releasing many values (above all in insertion order) is O(n²), the pattern the pool exists to avoid. OwnedProtect is a single protect-stack entry, not a precious-list root.

§Safety

Implementations must keep every SEXP passed to protect reachable by R’s collector for as long as the protector lives: safe code relies on that to hold the returned SEXP across allocations.

Required Methods§

Source

fn protect(&mut self, sexp: SEXP) -> SEXP

Root sexp until the protector drops, and return it.

sexp may be a fresh, unprotected object. Call it on R’s main thread, where the protector was made (both implementations are !Send).

Dyn Compatibility§

This trait is dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety".

Implementors§