pub struct Arc<T, S: Strategy> { /* private fields */ }Expand description
Transferable reference counted type.
This type works like a per-affinity (per-thread) sync::Arc. Each affinity gets a unique value that is shared by clones
of the Arc, but the ThreadAware implementation ensures that when moving to another affinity, the resulting
Arc will point to the value in the destination affinity. See new for information on constructing instances.
ThreadAware of different clones of the Arc result in “deduplication” in the destination affinity. The following
example demonstrates this using the counter implemented in the documentation for the ThreadAware trait.
let arc_affinity1 = Arc::<_, PerThread>::new(Counter::new);
let arc_affinity1_clone = arc_affinity1.clone();
arc_affinity1.increment_by(42);
assert_eq!(arc_affinity1.value(), 42);
let arc_affinity2 = arc_affinity1.relocated(affinity1, affinity2);
assert_eq!(arc_affinity2.value(), 0);
assert_eq!(arc_affinity1_clone.value(), 42);
arc_affinity2.increment_by(11);
let arc_affinity2_clone = arc_affinity1_clone.relocated(affinity1, affinity2);
assert_eq!(arc_affinity2_clone.value(), 11);Implementations§
Source§impl<T, S> Arc<T, S>
impl<T, S> Arc<T, S>
Sourcepub fn new(ctor: fn() -> T) -> Self
pub fn new(ctor: fn() -> T) -> Self
Creates a new Arc with the given value and strategy.
This variant takes a zero-argument constructor function (fn() -> T).
The constructor is invoked lazily and independently for each
processor the first time a PerCore is materialized on that processor (i.e. on
the first transfer into that processor). This guarantees that every processor obtains its own
freshly created T without requiring T: Clone or T: ThreadAware.
Requirements:
Tmust beSend + 'staticso it can live in the processor storage.- The provided function must be pure with respect to per-processor isolation (it should not
leak references into other processors). Any captured state should therefore be provided via
globally shareable mechanisms or prefer
new_withif you need to capture data that itself implementsThreadAware.
When transferring to another affinity which doesn’t yet contain a value, the constructor is called in the destination affinity to create a brand new instance.
For example, the counter type we implemented in the documentation for ThreadAware trait
can be used with new by passing the constructor function (note the absence of ()):
let container = Arc::<_, PerThread>::new(Counter::new);
let container_clone = container.clone();
container.increment_by(42);
assert_eq!(container.value(), 42);
assert_eq!(container_clone.value(), 42);Source§impl<T, S> Arc<T, S>where
T: 'static,
S: Strategy,
impl<T, S> Arc<T, S>where
T: 'static,
S: Strategy,
Sourcepub fn new_with<D>(data: D, f: fn(D) -> T) -> Self
pub fn new_with<D>(data: D, f: fn(D) -> T) -> Self
Creates a new Arc with a closure that will be called once per-processor to create the inner value.
The closure only gets called once for each processor, and it’s called only when a Arc is actually transferred
to another processor. The closure behaves like a RelocateFnOnce to ensure it captures only values that are safe to
transfer themselves.
This function can be used to create a Arc of a type that itself doesn’t implement ThreadAware because
we can ensure that each affinity will get its own, independenty-initialized value:
struct MyStruct {
inner: sync::Arc<Mutex<i32>>,
}
impl MyStruct {
fn new() -> Self {
Self {
inner: sync::Arc::new(Mutex::new(0)),
}
}
}
let container = Arc::<_, PerThread>::new_with((), |_| MyStruct::new());The constructor can depend on other values that implement ThreadAware (this example uses the Counter
defined in ThreadAware documentation):
struct MyStruct;
impl MyStruct {
fn new(value: i32) -> Self {
Self
}
}
let counter = Counter::new();
let container = Arc::<_, PerThread>::new_with(counter, |counter| MyStruct::new(counter.value()));Source§impl<T, S: Strategy> Arc<T, S>
impl<T, S: Strategy> Arc<T, S>
Sourcepub fn from_unaware(value: T) -> Self
pub fn from_unaware(value: T) -> Self
Creates a new Arc with the given value.
The value must implement Clone. When transferring to another affinity
which doesn’t yet contain a value, a new value is created by cloning the value in current
affinity and transferring it to the new affinity.
This is useful for types that do not implement ThreadAware. In such cases, the same value
is cloned for each affinity without any relocation logic.
For example, the counter type we implemented in the documentation for ThreadAware trait
can be used with new:
let arc = Arc::<_, PerThread>::new(Counter::new);
let arc_clone = arc.clone();
arc.increment_by(42);
assert_eq!(arc.value(), 42);
assert_eq!(arc_clone.value(), 42);Source§impl<T, S: Strategy> Arc<T, S>where
T: 'static,
impl<T, S: Strategy> Arc<T, S>where
T: 'static,
Sourcepub fn from_storage(
storage: Arc<RwLock<Storage<Arc<T>, S>>>,
current_affinity: PinnedAffinity,
) -> Self
pub fn from_storage( storage: Arc<RwLock<Storage<Arc<T>, S>>>, current_affinity: PinnedAffinity, ) -> Self
Creates a new Arc from the given storage and the current affinity.
If the resulting Arc is transferred to an affinity which does not have data in the storage,
it will behave like a sync::Arc.
§Panics
This may panic if the storage does not contain data for the current affinity.
Trait Implementations§
Source§impl<T: Ord, S: Strategy> Ord for Arc<T, S>
impl<T: Ord, S: Strategy> Ord for Arc<T, S>
Source§impl<T: PartialOrd, S: Strategy> PartialOrd for Arc<T, S>
impl<T: PartialOrd, S: Strategy> PartialOrd for Arc<T, S>
Source§impl<T, S: Strategy> ThreadAware for Arc<T, S>
impl<T, S: Strategy> ThreadAware for Arc<T, S>
Source§fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self
fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self
impl<T: Eq, S: Strategy> Eq for Arc<T, S>
Auto Trait Implementations§
impl<T, S> Freeze for Arc<T, S>
impl<T, S> !RefUnwindSafe for Arc<T, S>
impl<T, S> Send for Arc<T, S>
impl<T, S> Sync for Arc<T, S>
impl<T, S> Unpin for Arc<T, S>
impl<T, S> !UnwindSafe for Arc<T, S>
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> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<T> IntoEither for T
impl<T> IntoEither for T
Source§fn into_either(self, into_left: bool) -> Either<Self, Self>
fn into_either(self, into_left: bool) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left is true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read moreSource§fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
fn into_either_with<F>(self, into_left: F) -> Either<Self, Self>
self into a Left variant of Either<Self, Self>
if into_left(&self) returns true.
Converts self into a Right variant of Either<Self, Self>
otherwise. Read more