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: SEXPThe VECSXP that holds protected SEXPs. Anchored by R_PreserveObject.
capacity: usizeCurrent 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: usizeNext fresh VECSXP slot index (for when free_slots is empty).
len: usizeNumber of currently protected objects.
_nosend: PhantomData<Rc<()>>Implementations§
Source§impl ProtectPool
impl ProtectPool
Sourcepub const DEFAULT_CAPACITY: usize = 16
pub const DEFAULT_CAPACITY: usize = 16
Initial default capacity.
Sourcepub fn new(capacity: usize) -> Self
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.
Sourcepub fn with_capacity(capacity: usize) -> Self
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.
Sourcepub fn root(&mut self, value: impl IntoR) -> SEXP
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.
Sourcepub fn insert(&mut self, sexp: SEXP) -> ProtectKey
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.
Sourcepub fn release(&mut self, key: ProtectKey)
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.
Sourcepub fn get(&self, key: ProtectKey) -> Option<SEXP>
pub fn get(&self, key: ProtectKey) -> Option<SEXP>
Get the SEXP for a key, or None if the key is stale.
Sourcepub fn replace(&mut self, key: ProtectKey, sexp: SEXP) -> bool
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.
Sourcepub fn contains_key(&self, key: ProtectKey) -> bool
pub fn contains_key(&self, key: ProtectKey) -> bool
Check if a key is currently valid (not stale).
fn alloc_slot(&mut self) -> usize
Trait Implementations§
Source§impl Drop for ProtectPool
impl Drop for ProtectPool
Auto Trait Implementations§
impl !Send for ProtectPool
impl !Sync for ProtectPool
impl Freeze for ProtectPool
impl RefUnwindSafe for ProtectPool
impl Unpin for ProtectPool
impl UnsafeUnpin for ProtectPool
impl UnwindSafe for ProtectPool
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> SizeHint for Twhere
T: ?Sized,
impl<T> SizeHint for Twhere
T: ?Sized,
Source§default fn lower_bound(&self) -> usize
default fn lower_bound(&self) -> usize
core_io_internals)[u8; 12] could return any value between 0 and
12 inclusively as a correct implementation. Read moreSource§impl<T> SizedTypeProperties for T
impl<T> SizedTypeProperties for T
Source§#[doc(hidden)]const SIZE: usize = _
#[doc(hidden)]const SIZE: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGN: usize = _
#[doc(hidden)]const ALIGN: usize = _
sized_type_properties)Source§#[doc(hidden)]const ALIGNMENT: Alignment = _
#[doc(hidden)]const ALIGNMENT: Alignment = _
ptr_alignment_type)Source§#[doc(hidden)]const IS_ZST: bool = _
#[doc(hidden)]const IS_ZST: bool = _
sized_type_properties)Source§#[doc(hidden)]const LAYOUT: Layout = _
#[doc(hidden)]const LAYOUT: Layout = _
sized_type_properties)Source§#[doc(hidden)]const MAX_SLICE_LEN: usize = _
#[doc(hidden)]const MAX_SLICE_LEN: usize = _
sized_type_properties)[Self]. Read moreLayout§
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