pub struct HybridRc<T: ?Sized, State: RcState> { /* private fields */ }
Expand description

A hybrid reference-counting pointer.

See the module-level documentation for more details.

The inherent methods of HybridRc are all associated functions, which means that you have to call them as e.g. HybridRc::get_mut(&mut x) instead of x.get_mut(). This avoids conflicts with methods of the inner type T.

Implementations

Returns a mutable reference to the value, without checking for uniqueness.

See also
Safety

No other HybridRc or Weak for the same value must be dereferenced for the duration of the returned borrow.

Example
use hybrid_rc::Rc;

let mut a = Rc::new([1, 2, 3]);
// We know that there can't be any other references yet, so getting a mutable reference
// is safe here:
let mut_ref = unsafe { Rc::get_mut_unchecked(&mut a) };
mut_ref[0] = 42;

assert_eq!(a[..], [42, 2, 3]);

Returns a mutable reference to the value, iff the value is not shared with another HybridRc or Weak.

Returns None otherwise.

Provides a raw pointer to the referenced value

The counts are not affected in any way and the HybridRc is not consumed. The pointer is valid for as long there exists at least one HybridRc for the value.

Consumes the HybridRc<T, State>, returning the wrapped pointer.

To avoid a memory leak the pointer must be converted back to a HybridRc using HybridRc<T, State>::from_raw().

Reconstructs a HybridRc<T, State> from a raw pointer.

Creates a HybridRc<T, State> from a pointer that has been previously returned by a call to into_raw().

Safety

The raw pointer must have been previously returned by a call to HybridRc<T, State> for the same State and the same T or another compatible type that has the same size and alignment. The latter case amounts to mem::transmute() and is likely to produce undefined behaviour if not handled correctly.

The value must not have been dropped yet.

Creates a new Weak for the referenced value.

Example
use hybrid_rc::{Rc, Weak};

let strong = Rc::new(42i32);
let weak = Rc::downgrade(&strong);

assert_eq!(Rc::as_ptr(&strong), Weak::as_ptr(&weak));

Creates a new PinWeak for the referenced value.

Example
use hybrid_rc::{Rc, Weak};

let strong = Rc::pin(42i32);
let weak = Rc::downgrade_pin(&strong);

Checks if two HybridRcs point to the same allocation.

Checks if two pinned HybridRcs point to the same allocation.

Gets the approximate number of strong pointers to the inner value.

As shared pointers cannot access the local reference counter, Arc::strong_count() only provides a lower bound on the reference count at the moment of the call.

Please also understand that, if the count is greater than one, another thread might change the count at any time, including potentially between calling this method and acting on the result.

Examples
use hybrid_rc::{Rc, Arc};

let reference = Rc::new(42);
let _2nd_ref = Rc::clone(&reference);
let shared_ref = Rc::to_shared(&reference);
let _2nd_shared_ref = Arc::clone(&shared_ref);

assert_eq!(Rc::strong_count(&reference), 4);
// shared_ref only knows the count of shared references and that there is at least one
// local reference, so it will show 3 instead of 4:
assert_eq!(Arc::strong_count(&shared_ref), 3);

Gets the approximate number of strong pointers to the pinned inner value.

Gets the number of Weak pointers to this allocation.

Please understand that another thread may change the weak count at any time, including potentially between calling this method and acting on the result.

Examples
use hybrid_rc::{Rc, Weak};

let reference = Rc::new(42);
let weak = Rc::downgrade(&reference);
let _weak_2 = weak.clone();

assert_eq!(Rc::weak_count(&reference), 2);

Gets the number of PinWeak pointers to the pinned inner value.

Creates a new Rc<T>, moving data into a reference counted allocation.

If State is Local, the shared value is initially owned by the calling thread, so for another thread to assume ownership to_shared() must be used and all Rcs for the value must be dropped.

If State is Shared, initially the shared value has no owner thread, so any thread may call to_local() to assume ownership.

Examples
use hybrid_rc::Rc;

let rc = Rc::new(42i32);
// Cannot be used in another thread without using rc.to_shared()
std::thread::spawn(move || *rc).join(); // does not compile
use hybrid_rc::Arc;

let arc = Arc::new(42i32);

std::thread::spawn(move || assert!(*arc == 42)).join()?;

Creates a new HybridRc with uninitialized contents.

Creates a new HybridRc with uninitialized contents, with the memory being filled with 0 bytes.

See MaybeUninit::zeroed() for examples of correct and incorrect usage of this method.

Creates a new HybridRc with a possibly cyclic reference.

For this a reference to a Weak is passed to the closure that – after this function returns – will point to the new value itself. Attempting to upgrade the weak reference before new_cyclic returns will result in a ValueDropped error. However, the weak reference may be cloned freely and stored for use at a later time.

Creates a new Pin<HybridRc<T>>. If T does not implement Unpin, then data will be pinned in memory and unable to be moved.

Tries to creates a new Rc<T>, moving data into a reference counted allocation.

Errors

Will drop data and return Err(AllocError) if the allocation fails.

Please note that the global allocator on some systems may instead abort the process if an allocation failure happens.

Tries to construct a new HybridRc with uninitialized contents.

Errors

Will return Err(AllocError) if the allocation fails.

Please note that the global allocator on some systems may instead abort the process if an allocation failure happens.

Tries to construct a new HybridRc with uninitialized contents, with the memory being filled with 0 bytes.

See MaybeUninit::zeroed() for examples of correct and incorrect usage of this method.

Errors

Will return Err(AllocError) if the allocation fails.

Please note that the global allocator on some systems may instead abort the process if an allocation failure happens.

Returns the inner value, if this HybridRc is the only strong reference to it.

Any outstanding Weak references won’t be able to upgrade anymore when this succeeds.

Errors

If this is not the only strong reference to the shared value, an Err is returned with the same HybridRc that was passed in.

Examples
use hybrid_rc::Rc;

let reference = Rc::new(42);
let weak = Rc::downgrade(&reference);

let value = Rc::try_unwrap(reference).unwrap();
assert_eq!(value, 42);
assert!(weak.upgrade().is_err()); // Weaks cannot upgrade anymore.

Creates a new reference-counted slice with uninitialized contents.

Creates a new reference-counted slice with uninitialized contents, with the memory being filled with 0 bytes.

Copies the contents of a slice into a new HybridRc

Optimization for copyable types. Will become deprecated once specialization is stablilized.

Creates a new shared reference (Arc) for the referenced value.

Example
use hybrid_rc::{Rc, Arc};

let local = Rc::new(42i32);
let shared = Rc::to_shared(&local);

// `shared` can be safely transferred to another thread
std::thread::spawn(move || assert_eq!(*shared, 42i32)).join()?;

Creates a new pinned shared reference for the referenced value.

Example
use hybrid_rc::{Rc, Weak};

let strong = Rc::pin(42i32);
let shared = Rc::to_shared_pin(&strong);
assert!(Rc::ptr_eq_pin(&strong, &shared));

Increments the local strong reference count on the Rc<T> associated by the given pointer

Increases the local strong reference count as if a new Rc was cloned and kept alive. May panic in the unlikely case the platform-specific maximum for the reference count is reached.

Safety

The pointer must have been obtained through HybridRc<T, Local>::into_raw(), the value must still be live and have a local strong count of at least 1 when this method is invoked and this call must be performed on the same thread as where the original Rc was created.

Decrements the local strong reference count on the Rc<T> associated by the given pointer

If the local strong reference counter reaches 0, the value is no longer considered owned by the calling thread and if there are no shared strong references to keep the value alive, it will be dropped.

Safety

The pointer must have been obtained through HybridRc<T, Local>::into_raw(), the value must still be live and have a local strong count of at least 1 when this method is invoked and this call must be performed on the same thread as where the original Rc was created.

Creates a new local reference (Rc) for the referenced value.

Returns None if at least one Rc already exists on another thread.

Note: In no_std environments None is returned if at least one Rc exists on any thread.

Example
use hybrid_rc::{Rc, Arc};

let local = Rc::new(42i32);
let shared = Rc::to_shared(&local);

// `shared` can be safely transferred to another thread
std::thread::spawn(move || assert_eq!(*shared, 42i32)).join()?;

Creates a new pinned local reference for the referenced value.

Returns None if at least one Rc already exists on another thread.

Note: In no_std environments None is returned if at least one Rc exists on any thread.

Example
use hybrid_rc::{Arc, Weak};

let strong = Arc::pin(42i32);
let local = Arc::to_local_pin(&strong).unwrap();
assert!(Arc::ptr_eq_pin(&strong, &local));

Increments the shared strong reference count on the Arc<T> associated by the given pointer

Increases the shared strong reference count as if a new Arc was cloned and kept alive. May panic in the unlikely case the platform-specific maximum for the reference count is reached.

Safety

The pointer must have been obtained through HybridRc<T, Shared>::into_raw() and the value must still be live when this method is invoked.

Decrements the shared strong reference count on the Arc<T> associated by the given pointer

If the shared strong reference counter (including the implicit shared reference for local strong references) reaches 0, the value will be dropped.

Safety

The pointer must have been obtained through HybridRc<T, Shared>::into_raw() and the value must still be live when this method is invoked.

Makes a mutable reference into the given HybridRc.

If there are other strong references to the same value, then make_mut() will clone the inner value to a new allocation to ensure unique ownership. This is also referred to as clone-on-write.

However, if there are no other strong references to this allocation, but some Weak pointers, then the Weaks will be disassociated and the inner value will not be cloned.

See also: get_mut(), which will fail rather than cloning the inner value or diassociating Weaks.

Example
use hybrid_rc::Rc;

let mut reference = Rc::new(42);

*Rc::make_mut(&mut reference) += 2;          // Won't clone anything
let mut reference_2 = Rc::clone(&reference); // Won't clone inner value
*Rc::make_mut(&mut reference) += 1;         // Clones inner data
*Rc::make_mut(&mut reference) *= 2;        // Won't clone anything
*Rc::make_mut(&mut reference_2) /= 4;       // Won't clone anything

// Now `reference` and `reference_2` point to different allocations.
assert_eq!(*reference, 90);
assert_eq!(*reference_2, 11);

Assumes the value is initialized and converts to HybridRc<T, State>.

Safety

You need to provide the same guarantees as for MaybeUninit::assume_init(). Calling this when the value is not yet fully initialized causes immediate undefined behavior.

Examples
use hybrid_rc::Rc;

let mut reference = Rc::<i64>::new_uninit();

let reference = unsafe {
	// Deferred initialization
	Rc::get_mut_unchecked(&mut reference).as_mut_ptr().write(1337);
    reference.assume_init()
};

assert_eq!(*reference, 1337)

Assumes the values are initialized and converts to HybridRc<[T], State>.

Safety

You need to provide the same guarantees as for MaybeUninit::assume_init(). Calling this when the whole slice is not yet fully initialized causes immediate undefined behavior.

Tries to downcast the HybridRc<dyn Any, _> to a concrete type.

Errors

If a downcast failed, the original HybridRc is returned in Err

Example
use std::any::Any;
use std::mem::drop;
use hybrid_rc::Rc;

let value = 42i32;
let concrete = Rc::new(value);
let any: Rc<dyn Any> = Rc::into(concrete);

let any = any.downcast::<String>().unwrap_err();

assert_eq!(*any.downcast::<i32>().unwrap(), 42);

Tries to downcast the HybridRc<dyn Any + Sync + Send, _> to a concrete type.

Errors

If a downcast failed, the original HybridRc is returned in Err

Example
use std::any::Any;
use std::mem::drop;
use hybrid_rc::Rc;

let value = 42i32;
let concrete = Rc::new(value);
let any: Rc<dyn Any + Sync + Send> = Rc::into(concrete);

let any = any.downcast::<String>().unwrap_err();

assert_eq!(*any.downcast::<i32>().unwrap(), 42);

Trait Implementations

Performs the conversion.

Immutably borrows from an owned value. Read more

Creates another Rc for the same value.

Example
use hybrid_rc::Rc;

let first = Rc::new(42i32);
let second = Rc::clone(&first);

assert_eq!(Rc::as_ptr(&first), Rc::as_ptr(&second));

Performs copy-assignment from source. Read more

Creates another Arc for the same value.

Example
use hybrid_rc::Arc;

let first = Arc::new(42i32);
let second = Arc::clone(&first);

assert_eq!(Arc::as_ptr(&first), Arc::as_ptr(&second));

let value = std::thread::spawn(move || *second)
  .join()?;
assert_eq!(*first, value);

Performs copy-assignment from source. Read more

Formats the value using the given formatter. Read more

Creates a new HybridRc, with the Default value for T.

The resulting type after dereferencing.

Dereferences the value.

Formats the value using the given formatter. Read more

Drops the HybridRc.

This will decrement the appropriate reference count depending on State. If both strong reference counts reach zero then the only other references (if any) are Weak. In that case the inner value is dropped.

Allocate a reference-counted slice and clone the elements of src into it.

Example
use hybrid_rc::Rc;

let vecs = [
	vec![1,2,3],
	vec![4,5,6],
];
let rc: Rc<[_]> = Rc::from(&vecs[..]);
assert_eq!(&rc[..], &vecs);

Allocate a reference-counted str and copy src into it.

Example
use hybrid_rc::Rc;

let a: Rc<str> = Rc::from("foobar");
assert_eq!(&a[..], "foobar");

Performs the conversion.

Creates a new HybridRc<T, State> from a clone-on-write pointer by copying its content.

Example
use hybrid_rc::Rc;
use std::borrow::Cow;

let cow: Cow<str> = Cow::Borrowed("foobar");
let a: Rc<str> = Rc::from(cow);
assert_eq!(&a[..], "foobar");

Converts a HybridRc<[T; N], State> into a HybridRc<[T], State>

Workaround for coercion as long as CoerceUnsized is unstable.

Converts an Rc<T> into an Arc<T>.

See to_shared().

Upcasts a HybridRc<T, State> into a HybridRc<dyn Any, State>

Upcasts a HybridRc<T, State> into a HybridRc<dyn Any + Sync + Send, State>

Allocate a reference-counted str and copy src into it.

Example
use hybrid_rc::Rc;

let string: String = "foobar".to_owned();
let a: Rc<str> = Rc::from(string);
assert_eq!(&a[..], "foobar");

Moves a T into an HybridRc<T, State>

Equivalent to calling [HybridRc::new(src)].

Allocate a reference-counted slice and move src’s items into it.

Example
use hybrid_rc::Rc;

let vec = vec!["a","b","c"];
let rc: Rc<[_]> = Rc::from(vec);
assert_eq!(&rc[..], &["a", "b", "c"]);

Takes each element in the Iterator and collects it into an HybridRc<[T], State>.

Performance characteristics

Collecion is done by first collecting into a Vec<T>.

This will allocate as many times as needed for constructing the Vec<T> and then it will allocate once for turning the Vec<T> into the HybridRc<[T], State>.

Once specialization is stablilized this will be optimized for TrustedLen iterators.

Feeds this value into the given Hasher. Read more

Feeds a slice of this type into the given Hasher. Read more

Comparison for HybridRcs.

The two are compared by calling cmp() on their inner values.

Compares and returns the maximum of two values. Read more

Compares and returns the minimum of two values. Read more

Restrict a value to a certain interval. Read more

Equality for HybridRcs.

Two HybridRcs are equal if their inner values are equal, independent of if they are stored in the same allocation.

This method tests for !=.

Partial comparison for HybridRcs.

The two are compared by calling partial_cmp() on their inner values.

This method tests less than (for self and other) and is used by the < operator. Read more

This method tests less than or equal to (for self and other) and is used by the <= operator. Read more

This method tests greater than (for self and other) and is used by the > operator. Read more

This method tests greater than or equal to (for self and other) and is used by the >= operator. Read more

Formats the value using the given formatter.

If the # flag is used, the state (shared/local) is written after the address.

Tries to convert a HybridRc<[T], State> into a HybridRc<[T; N], State>

Only succeeds if the length matches exactly.

The type returned in the event of a conversion error.

Tries to convert an Arc<T> into an Rc<T>.

See to_local().

The type returned in the event of a conversion error.

HybridRc<T> is always Unpin itself, because the data value is on the heap, so moving HybridRc<T> doesn’t move the content even if T is not Unpin.

This allows unpinning e.g. Pin<Box<HybridRc<T>>> but not any Pin<HybridRc<T>>!

Auto Trait Implementations

Blanket Implementations

Gets the TypeId of self. Read more

Immutably borrows from an owned value. Read more

Mutably borrows from an owned value. Read more

Performs the conversion.

Performs the conversion.

Performs the conversion.

The resulting type after obtaining ownership.

Creates owned data from borrowed data, usually by cloning. Read more

🔬 This is a nightly-only experimental API. (toowned_clone_into)

Uses borrowed data to replace owned data, usually by cloning. Read more

Converts the given value to a String. Read more

The type returned in the event of a conversion error.

Performs the conversion.

The type returned in the event of a conversion error.

Performs the conversion.