pub struct PooledMut<T: ?Sized> { /* private fields */ }Expand description
Exclusive handle to a pooled item that prevents double-use through the type system.
PooledMut<T> provides exclusive ownership of an item stored in an OpaquePool and
ensures that each handle can only be used once. Unlike Pooled<T>, this type does not
implement Copy or Clone, making it impossible to accidentally create multiple
handles to the same pooled item or use a handle after it has been consumed.
This is the recommended handle type for most use cases as it provides stronger safety
guarantees and enables safe removal operations without requiring unsafe code.
§Key Features
- Exclusive ownership: Each handle represents unique access to one pooled item
- Single-use guarantee: Cannot be copied, cloned, or reused after consumption
- Safe removal: Removal methods consume the handle, preventing use-after-free
- Direct value access: Implements
std::ops::Derefandstd::ops::DerefMut - Mutable access: Full read-write access to the stored value
- Conversion to shared: Use
into_shared()to enable copying - Pinning support: Safe
std::pin::Pinaccess for both&Tand&mut T - Type erasure: Use
erase()to convert toPooledMut<()> - Pointer access: Raw pointer access via
ptr()for advanced cases
§Safety Benefits
PooledMut<T> provides stronger compile-time guarantees than Pooled<T>:
- No double-use: Cannot be copied or cloned, preventing accidental reuse
- Safe removal: Pool removal methods consume the handle, making reuse impossible
- Move semantics: Handle is moved/consumed by operations, enforcing single use
- Type system enforcement: Rust’s ownership system prevents use-after-move errors
§Relationship with Pooled<T>
PooledMut<T> can be converted to Pooled<T> using into_shared()
when you need to share access across multiple references. This conversion is one-way;
you cannot convert back from Pooled<T> to PooledMut<T>.
§Examples
§Safe exclusive access and removal
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// Insert and get exclusive handle
// SAFETY: String matches the layout used to create the pool
let mut item = unsafe { pool.insert("Hello".to_string()) };
// Direct access through Deref and DerefMut
assert_eq!(&*item, "Hello");
item.push_str(", World!");
assert_eq!(&*item, "Hello, World!");
// Safe removal - handle is consumed, preventing reuse
pool.remove_mut(item);
// item is now moved and cannot be used again!§Converting to shared access
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<u64>().build();
// SAFETY: u64 matches the layout used to create the pool
let exclusive = unsafe { pool.insert(42_u64) };
// Convert to shared handle for copying
let shared = exclusive.into_shared();
let shared_copy = shared; // Now can copy freely
assert_eq!(*shared_copy, 42);
// Removal now requires unsafe since multiple handles could exist
// SAFETY: No other copies of the handle will be used after this call
unsafe { pool.remove(&shared_copy) };§Pinning support
use std::pin::Pin;
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool
let item = unsafe { pool.insert("Pinned".to_string()) };
// Get pinned references safely
let pinned_ref: Pin<&String> = item.as_pin();
assert_eq!(&**pinned_ref, "Pinned");
pool.remove_mut(item);§Thread Safety
This type has the same thread safety properties as Pooled<T>. It is thread-safe
(Send + Sync) if and only if T implements Sync. When T is Sync,
the handle can be moved between threads or shared between threads safely.
Implementations§
Source§impl<T: ?Sized> PooledMut<T>
impl<T: ?Sized> PooledMut<T>
Sourcepub fn ptr(&self) -> NonNull<T>
pub fn ptr(&self) -> NonNull<T>
Returns a pointer to the inserted value.
This provides access to the value stored in the pool. The owner of the handle has
exclusive access to the value and may both read and write and may create both & shared
and &mut exclusive references to the item.
§Example
use std::alloc::Layout;
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let mut item = unsafe { pool.insert("Hello".to_string()) };
// Read data back using Deref.
assert_eq!(&*item, "Hello");
// Can also write to it using DerefMut.
item.push_str(", World!");
assert_eq!(&*item, "Hello, World!");Converts this exclusive handle to a shared handle.
This allows multiple shared handles to exist to the same pooled item.
The returned Pooled<T> handle can be copied and shared, but removal
operations will require unsafe code again.
§Example
use std::alloc::Layout;
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let item = unsafe { pool.insert("Test".to_string()) };
// Convert to shared handle.
let shared = item.into_shared();
// Can now copy the handle.
let shared_copy = shared;
// But removal requires unsafe again.
unsafe { pool.remove(&shared_copy) };Sourcepub fn erase(self) -> PooledMut<()>
pub fn erase(self) -> PooledMut<()>
Erases the type information from this PooledMut<T> handle, returning a PooledMut<()>.
This is useful when you want to store handles of different types in the same collection or pass them to code that doesn’t need to know the specific type.
The handle remains functionally equivalent and can still be used to remove the item from the pool and drop it. The only change is the removal of the type information.
§Example
use std::alloc::Layout;
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let item = unsafe { pool.insert("Test".to_string()) };
// Erase type information.
let erased = item.erase();
// Cast back to original type for safe access.
// SAFETY: We know this contains a String.
let typed_ptr = erased.ptr().cast::<String>();
let value = unsafe { typed_ptr.as_ref() };
assert_eq!(value, "Test");
// Can still remove the item.
pool.remove_mut(erased);Sourcepub fn as_pin(&self) -> Pin<&T>
pub fn as_pin(&self) -> Pin<&T>
Returns a pinned reference to the value stored in the pool.
Since values in the pool are always pinned (they never move once inserted),
this method provides safe access to Pin<&T> without requiring unsafe code.
§Example
use std::pin::Pin;
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let handle = unsafe { pool.insert("hello".to_string()) };
let pinned: Pin<&String> = handle.as_pin();
assert_eq!(pinned.len(), 5);Sourcepub fn as_pin_mut(&mut self) -> Pin<&mut T>
pub fn as_pin_mut(&mut self) -> Pin<&mut T>
Returns a pinned mutable reference to the value stored in the pool.
Since values in the pool are always pinned (they never move once inserted),
this method provides safe access to Pin<&mut T> without requiring unsafe code.
§Example
use std::pin::Pin;
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let mut handle = unsafe { pool.insert("hello".to_string()) };
let mut pinned: Pin<&mut String> = handle.as_pin_mut();
// Can use Pin methods or deref to &mut StringTrait Implementations§
Source§impl<T: ?Sized> Deref for PooledMut<T>
impl<T: ?Sized> Deref for PooledMut<T>
Source§fn deref(&self) -> &Self::Target
fn deref(&self) -> &Self::Target
Provides direct access to the value stored in the pool.
This allows the handle to be used as if it were a reference to the stored value.
§Example
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let string_handle = unsafe { pool.insert("hello".to_string()) };
// Access string methods directly.
assert_eq!(string_handle.len(), 5);
assert!(string_handle.starts_with("he"));Source§impl<T: ?Sized> DerefMut for PooledMut<T>
impl<T: ?Sized> DerefMut for PooledMut<T>
Source§fn deref_mut(&mut self) -> &mut Self::Target
fn deref_mut(&mut self) -> &mut Self::Target
Provides direct mutable access to the value stored in the pool.
This allows the handle to be used as if it were a mutable reference to the stored value.
§Example
use opaque_pool::OpaquePool;
let mut pool = OpaquePool::builder().layout_of::<String>().build();
// SAFETY: String matches the layout used to create the pool.
let mut string_handle = unsafe { pool.insert("hello".to_string()) };
// Mutate the string directly.
string_handle.push_str(" world");
assert_eq!(*string_handle, "hello world");