Skip to main content

ProtectPool

Struct ProtectPool 

Source
pub struct ProtectPool {
    backing: SEXP,
    capacity: usize,
    generations: Vec<u32>,
    free_slots: Vec<usize>,
    next_slot: usize,
    len: usize,
    _nosend: PhantomData<Rc<()>>,
}
Expand description

An owned root set for R objects, held in one R list, with generational keys.

See the module docs for the two uses: the per-call root set (root) and the cross-call pool (insert / release).

§Example

ⓘ
let mut pool = ProtectPool::new(ProtectPool::DEFAULT_CAPACITY);

// Root a value until the pool drops.
let ints = pool.root(vec![1, 2, 3]);

// Root a value with a key, to release it early.
let key = pool.insert(SEXP::scalar_integer(42));
let sexp = pool.get(key).unwrap();
pool.release(key);
assert!(pool.get(key).is_none());

The pool is !Send and !Sync: R’s API belongs to its main thread.

ⓘ
fn assert_send<T: Send>() {}
assert_send::<miniextendr_api::ProtectPool>();
ⓘ
fn assert_sync<T: Sync>() {}
assert_sync::<miniextendr_api::ProtectPool>();

Fields§

§backing: SEXP

The VECSXP that holds protected SEXPs. Anchored by R_PreserveObject.

§capacity: usize

Current capacity of the backing VECSXP.

§generations: Vec<u32>

Generation counter per VECSXP slot. Incremented on each release. A key is valid iff generations[key.slot] == key.generation.

§free_slots: Vec<usize>

Free VECSXP slot indices for reuse.

§next_slot: usize

Next fresh VECSXP slot index (for when free_slots is empty).

§len: usize

Number of currently protected objects.

§_nosend: PhantomData<Rc<()>>

Implementations§

Source§

impl ProtectPool

Source

pub const DEFAULT_CAPACITY: usize = 16

Initial default capacity.

Source

pub fn new(capacity: usize) -> Self

Create a pool with room for capacity objects before it grows.

Same as with_capacity. Call it on R’s main thread.

§Panics

Panics if capacity exceeds R_xlen_t::MAX.

Source

pub fn with_capacity(capacity: usize) -> Self

Create a pool with room for capacity objects before it grows.

Allocates the backing list and preserves it. Call it on R’s main thread.

§Panics

Panics if capacity exceeds R_xlen_t::MAX.

Source

pub fn root(&mut self, value: impl IntoR) -> SEXP

Convert value to an R object, root it until the pool drops, and return it.

The “keep this alive and give it back” call of the per-call root set. A SEXP converts to itself, so pool.root(sexp) roots an existing object, fresh and unprotected or not. Nothing allocates between the conversion and the insert except the pool’s own growth, which keeps the object reachable (see insert).

There is no key: the object is released with the pool. Use insert to release it earlier. Call it on R’s main thread.

Source

pub fn insert(&mut self, sexp: SEXP) -> ProtectKey

Root sexp, returning a generational key.

sexp stays rooted until release is called with the key, its slot is replaced, or the pool drops. A key dropped without release keeps it rooted until the pool drops.

sexp may be a fresh, unprotected object. Inserting into a free slot allocates nothing. When the pool is full it grows, which allocates a new backing list; sexp stays on R’s protect stack until then, so the collection that allocation can trigger cannot reclaim it. Call it on R’s main thread.

§Panics

Panics if the pool has grown beyond u32::MAX slots.

Source

pub fn release(&mut self, key: ProtectKey)

Release the object key roots and free its slot for reuse.

A stale key (already released) is a no-op. Allocates nothing. Call it on R’s main thread.

Source

pub fn get(&self, key: ProtectKey) -> Option<SEXP>

Get the SEXP for a key, or None if the key is stale.

Source

pub fn replace(&mut self, key: ProtectKey, sexp: SEXP) -> bool

Root sexp in key’s slot, in place of the object there.

Returns true if the key was valid and the value was replaced. The previous object is no longer rooted by this slot. Returns false for a stale key and does nothing: sexp is then not rooted.

This is the pool equivalent of R_Reprotect: O(1), and it allocates nothing, so a fresh sexp is safe. Call it on R’s main thread.

Source

pub fn contains_key(&self, key: ProtectKey) -> bool

Check if a key is currently valid (not stale).

Source

pub fn len(&self) -> usize

Number of currently protected objects.

Source

pub fn is_empty(&self) -> bool

Whether the pool is empty.

Source

pub fn capacity(&self) -> usize

Current capacity of the backing VECSXP.

Source

fn is_full(&self) -> bool

Whether the next insert grows the backing list.

Source

fn alloc_slot(&mut self) -> usize

Source

fn grow(&mut self)

Double the backing list. It allocates, so the caller keeps any object it is about to store reachable.

Trait Implementations§

Source§

impl Drop for ProtectPool

Source§

fn drop(&mut self)

Executes the destructor for this type. Read more
Source§

fn pin_drop(self: Pin<&mut Self>)

🔬This is a nightly-only experimental API. (pin_ergonomics)
Execute the destructor for this type, but different to Drop::drop, it requires self to be pinned. Read more
Source§

impl Protector for ProtectPool

Source§

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

Root sexp until the protector drops, and return it. Read more

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> SizeHint for T
where T: ?Sized,

Source§

default fn lower_bound(&self) -> usize

🔬This is a nightly-only experimental API. (core_io_internals)
Returns a lower bound on the number of elements this container-like item contains. For example, an array [u8; 12] could return any value between 0 and 12 inclusively as a correct implementation. Read more
Source§

default fn upper_bound(&self) -> Option<usize>

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an upper bound on the number of elements this container-like item contains if it can be determined, otherwise None. Read more
Source§

final fn size_hint(&self) -> (usize, Option<usize>)

🔬This is a nightly-only experimental API. (core_io_internals)
Returns an estimate for the number of elements this container like type contains. Read more
Source§

impl<T> SizedTypeProperties for T

Source§

#[doc(hidden)]
const SIZE: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const ALIGNMENT: Alignment = _

🔬This is a nightly-only experimental API. (ptr_alignment_type)
Source§

#[doc(hidden)]
const IS_ZST: bool = _

🔬This is a nightly-only experimental API. (sized_type_properties)
true if this type requires no storage. false if its size is greater than zero. Read more
Source§

#[doc(hidden)]
const LAYOUT: Layout = _

🔬This is a nightly-only experimental API. (sized_type_properties)
Source§

#[doc(hidden)]
const MAX_SLICE_LEN: usize = _

🔬This is a nightly-only experimental API. (sized_type_properties)
The largest safe length for a [Self]. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = !

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, !>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.

Layout§

Note: Most layout information is completely unstable and may even differ between compilations. The only exception is types with certain repr(...) attributes. Please see the Rust Reference's “Type Layout” chapter for details on type layout guarantees.

Size: 80 bytes