pub struct OwnedRefMut<T, C = DefaultConfig>where
    T: Clear + Default,
    C: Config,{ /* private fields */ }
Expand description

An owned guard that allows exclusive, mutable access to an object in a pool.

An OwnedRefMut<T> functions more or less identically to an owned Box<T>: it can be passed to functions, stored in structure fields, and borrowed mutably or immutably, and can be owned for arbitrary lifetimes. The difference is that, unlike a Box<T>, the memory allocation for the T lives in the Pool; when an OwnedRefMut is created, it may reuse memory that was allocated for a previous pooled object that has been cleared. Additionally, the OwnedRefMut may be downgraded to an OwnedRef which may be shared freely, essentially turning the Box into an Arc.

This is returned by Pool::create_owned.

While the guard exists, it indicates to the pool that the item the guard references is currently being accessed. If the item is removed from the pool while the guard exists, theremoval will be deferred until all guards are dropped.

Unlike RefMut, which borrows the pool, an OwnedRefMut clones the Arc around the pool. Therefore, it keeps the pool from being dropped until all such guards have been dropped. This means that an OwnedRefMut may be held for an arbitrary lifetime.

Examples

use std::sync::Arc;

let pool: Arc<Pool<String>> = Arc::new(Pool::new());

// Create a new pooled item, returning an owned guard that allows mutable
// access to the new item.
let mut item = pool.clone().create_owned().unwrap();
// Return a key that allows indexing the created item once the guard
// has been dropped.
let key = item.key();

// Mutate the item.
item.push_str("Hello");
// Drop the guard, releasing mutable access to the new item.
drop(item);

/// Other threads may now (immutably) access the item using the returned key.
thread::spawn(move || {
   assert_eq!(pool.get(key).unwrap(), String::from("Hello"));
}).join().unwrap();
use std::sync::Arc;

let pool: Arc<Pool<String>> = Arc::new(Pool::new());

// Create a new item, returning an owned, mutable guard.
let mut value = pool.clone().create_owned().unwrap();

// Now, the original `Arc` clone of the pool may be dropped, but the
// returned `OwnedRefMut` can still access the value.
drop(pool);

value.push_str("hello world");
assert_eq!(value, String::from("hello world"));

Unlike RefMut, an OwnedRefMut may be stored in a struct which must live for the 'static lifetime:

use sharded_slab::pool::OwnedRefMut;
use std::sync::Arc;

pub struct MyStruct {
    pool_ref: OwnedRefMut<String>,
    // ... other fields ...
}

// Suppose this is some arbitrary function which requires a value that
// lives for the 'static lifetime...
fn function_requiring_static<T: 'static>(t: &T) {
    // ... do something extremely important and interesting ...
}

let pool: Arc<Pool<String>> = Arc::new(Pool::new());

// Create a new item, returning a mutable owned reference.
let pool_ref = pool.clone().create_owned().unwrap();

let my_struct = MyStruct {
    pool_ref,
    // ...
};

// We can use `my_struct` anywhere where it is required to have the
// `'static` lifetime:
function_requiring_static(&my_struct);

OwnedRefMuts may be sent between threads:

use std::{thread, sync::Arc};

let pool: Arc<Pool<String>> = Arc::new(Pool::new());

let mut value = pool.clone().create_owned().unwrap();
let key = value.key();

thread::spawn(move || {
    value.push_str("hello world");
    // ...
}).join().unwrap();

// Once the `OwnedRefMut` has been dropped by the other thread, we may
// now access the value immutably on this thread.

assert_eq!(pool.get(key).unwrap(), String::from("hello world"));

Downgrading from a mutable to an immutable reference:

use std::{thread, sync::Arc};

let pool: Arc<Pool<String>> = Arc::new(Pool::new());

let mut value = pool.clone().create_owned().unwrap();
let key = value.key();
value.push_str("hello world");

// Downgrade the mutable owned ref to an immutable owned ref.
let value = value.downgrade();

// Once the `OwnedRefMut` has been downgraded, other threads may
// immutably access the pooled value:
thread::spawn(move || {
    assert_eq!(pool.get(key).unwrap(), String::from("hello world"));
}).join().unwrap();

// This thread can still access the pooled value through the
// immutable owned ref:
assert_eq!(value, String::from("hello world"));

Implementations§

source§

impl<T, C> OwnedRefMut<T, C>where T: Clear + Default, C: Config,

source

pub fn key(&self) -> usize

Returns the key used to access this guard

source

pub fn downgrade(self) -> OwnedRef<T, C>

Downgrades the owned mutable guard to an owned immutable guard, allowing access to the pooled value from other threads.

Examples
let pool = Arc::new(Pool::<String>::new());

let mut guard_mut = pool.clone().create_owned().unwrap();
let key = guard_mut.key();
guard_mut.push_str("Hello");

// The pooled string is currently borrowed mutably, so other threads
// may not access it.
let pool2 = pool.clone();
thread::spawn(move || {
    assert!(pool2.get(key).is_none())
}).join().unwrap();

// Downgrade the guard to an immutable reference.
let guard = guard_mut.downgrade();

// Now, other threads may also access the pooled value.
let pool2 = pool.clone();
thread::spawn(move || {
    let guard = pool2.get(key)
        .expect("the item may now be referenced by other threads");
    assert_eq!(guard, String::from("Hello"));
}).join().unwrap();

// We can still access the value immutably through the downgraded guard.
assert_eq!(guard, String::from("Hello"));

Trait Implementations§

source§

impl<T, C> Debug for OwnedRefMut<T, C>where T: Debug + Clear + Default, C: Config,

source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
source§

impl<T, C> Deref for OwnedRefMut<T, C>where T: Clear + Default, C: Config,

§

type Target = T

The resulting type after dereferencing.
source§

fn deref(&self) -> &Self::Target

Dereferences the value.
source§

impl<T, C> DerefMut for OwnedRefMut<T, C>where T: Clear + Default, C: Config,

source§

fn deref_mut(&mut self) -> &mut Self::Target

Mutably dereferences the value.
source§

impl<T, C> Drop for OwnedRefMut<T, C>where T: Clear + Default, C: Config,

source§

fn drop(&mut self)

Executes the destructor for this type. Read more
source§

impl<T, C> PartialEq<T> for OwnedRefMut<T, C>where T: PartialEq<T> + Clear + Default, C: Config,

source§

fn eq(&self, other: &T) -> bool

This method tests for self and other values to be equal, and is used by ==.
1.0.0 · source§

fn ne(&self, other: &Rhs) -> bool

This method tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
source§

impl<T, C> Send for OwnedRefMut<T, C>where T: Sync + Clear + Default, C: Config,

source§

impl<T, C> Sync for OwnedRefMut<T, C>where T: Sync + Clear + Default, C: Config,

Auto Trait Implementations§

§

impl<T, C = DefaultConfig> !RefUnwindSafe for OwnedRefMut<T, C>

§

impl<T, C> Unpin for OwnedRefMut<T, C>

§

impl<T, C = DefaultConfig> !UnwindSafe for OwnedRefMut<T, C>

Blanket Implementations§

source§

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

source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
source§

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

source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
source§

impl<T> BorrowMut<T> for Twhere 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 Twhere 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, U> TryFrom<U> for Twhere U: Into<T>,

§

type Error = Infallible

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

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
source§

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

§

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.