ThreadAware

Trait ThreadAware 

Source
pub trait ThreadAware {
    // Required method
    fn relocated(
        self,
        source: MemoryAffinity,
        destination: PinnedAffinity,
    ) -> Self;
}
Expand description

Marks types that correctly handle isolation when transferred between threads (affinities).

The basic invariant of the ThreadAware trait is that the value returned by ThreadAware::relocated must be as independent as possible from any state on the source (or any other) affinity in the sense that interacting with the object should not result in contention over synchronization primitives when this interaction happens in parallel with interactions with related values (e.g. clones) on other affinities.

What this means depends on the type, but there are a couple of common implementation strategies:

  • Return self - this implies that the value doesn’t have any dependency on other values that may result in synchronization primitive contention, so it can be transferred as is. This approach can be also be achieved by wrapping a value in the Unaware type.
  • Construct a per-affinity value - with this approach, each affinity gets its own independently-initialized value. The Arc::new_with function facilitates this approach.
  • Utilize true sharing in a controlled manner - have some data that is actually shared between the values on different affinities, but in a controlled manner that minimizes the contention for the synchronization primitives necessary. This is a more advanced technique allowing for designs that minimize contention while avoiding wasting resources by duplicating them for each affinity.

As an example, let’s implement a counter that counts per-affinity. This counter will use interior mutability to to allow increments with just a shared reference, but we want to avoid contention on the internal state, so each affinity will get an independent counter.

#[derive(Clone)]
struct Counter {
    value: Arc<AtomicI32>,
}

impl Counter {
    fn new() -> Self {
        Self {
            value: Arc::new(AtomicI32::new(0)),
        }
    }

    fn increment_by(&self, value: i32) {
        self.value.fetch_add(value, Ordering::AcqRel);
    }

    fn value(&self) -> i32 {
        self.value.load(Ordering::Acquire)
    }
}

impl ThreadAware for Counter {
    fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self {
        Self {
            // Initialize a new value in the destination affinity independent
            // of the source affinity.
            value: Arc::new(AtomicI32::new(0)),
        }
    }
}

Note that this trait is independent of the Send trait as there can be usages of isolated affinities with multiple affinities on a single thread. However, that is a fairly specific use case, so types that implement ThreadAware should generally also implement Send.

Required Methods§

Source

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Consume a value and return a value in the destination affinity.

When implementing this function, you can assume self belongs to the source affinity, but it’s not guaranteed that source and destination will be different. Note that “belonging to an affinity” is a logical concept that may not have a direct representation in the code. In particular, when a value is first constructed, the source affinity may not be known to that value until it’s transferred for the first time, at which point it can utilize the source parameter to determine the original affinity.

When calling this function, you must ensure that self belongs to the source affinity, and try to avoid calling transfer when source and destination match as that’s a useless operation and transfer implementations may be non-trivial.

Dyn Compatibility§

This trait is not dyn compatible.

In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.

Implementations on Foreign Types§

Source§

impl ThreadAware for &'static str

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for &Path

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for bool

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for char

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for f32

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for f64

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for i8

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for i16

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for i32

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for i64

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for isize

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for u8

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for u16

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for u32

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for u64

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for ()

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for usize

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for String

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for Duration

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl ThreadAware for PathBuf

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<A, B, C, D, E, F, G, H, I, J, K, L> ThreadAware for (A, B, C, D, E, F, G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<B, C, D, E, F, G, H, I, J, K, L> ThreadAware for (B, C, D, E, F, G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<C, D, E, F, G, H, I, J, K, L> ThreadAware for (C, D, E, F, G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<D, E, F, G, H, I, J, K, L> ThreadAware for (D, E, F, G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<E, F, G, H, I, J, K, L> ThreadAware for (E, F, G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<F, G, H, I, J, K, L> ThreadAware for (F, G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<G, H, I, J, K, L> ThreadAware for (G, H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<H, I, J, K, L> ThreadAware for (H, I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<I, J, K, L> ThreadAware for (I, J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<J, K, L> ThreadAware for (J, K, L)

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<K, L> ThreadAware for (K, L)
where K: ThreadAware, L: ThreadAware,

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<K, V> ThreadAware for HashMap<K, V>
where K: ThreadAware + Eq + Hash, V: ThreadAware,

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<L> ThreadAware for (L,)
where L: ThreadAware,

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<R> ThreadAware for fn() -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, A, B, C, D, E, F, G, H, I, J, K, L> ThreadAware for fn(A, B, C, D, E, F, G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, B, C, D, E, F, G, H, I, J, K, L> ThreadAware for fn(B, C, D, E, F, G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, C, D, E, F, G, H, I, J, K, L> ThreadAware for fn(C, D, E, F, G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, D, E, F, G, H, I, J, K, L> ThreadAware for fn(D, E, F, G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, E, F, G, H, I, J, K, L> ThreadAware for fn(E, F, G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, F, G, H, I, J, K, L> ThreadAware for fn(F, G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, G, H, I, J, K, L> ThreadAware for fn(G, H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, H, I, J, K, L> ThreadAware for fn(H, I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, I, J, K, L> ThreadAware for fn(I, J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, J, K, L> ThreadAware for fn(J, K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, K, L> ThreadAware for fn(K, L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<R, L> ThreadAware for fn(L) -> R

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<T> ThreadAware for Option<T>
where T: ThreadAware,

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<T> ThreadAware for Arc<T>

Source§

fn relocated( self, _source: MemoryAffinity, _destination: PinnedAffinity, ) -> Self

Source§

impl<T> ThreadAware for Vec<T>
where T: ThreadAware,

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Source§

impl<T, E> ThreadAware for Result<T, E>
where T: ThreadAware, E: ThreadAware,

Source§

fn relocated(self, source: MemoryAffinity, destination: PinnedAffinity) -> Self

Implementors§

Source§

impl<T> ThreadAware for Unaware<T>

Source§

impl<T, D> ThreadAware for Closure<T, D>
where D: ThreadAware,

Source§

impl<T, D> ThreadAware for ClosureMut<T, D>
where D: ThreadAware,

Source§

impl<T, D> ThreadAware for ClosureOnce<T, D>
where D: ThreadAware,

Source§

impl<T, S: Strategy> ThreadAware for thread_aware::Arc<T, S>