rusttypesheap-memory

How to structure the type of a Rust object to share between threads


I'm writing an application with two threads: a UI thread and compute thread. I want them to share a vector of buffers with type T. Since it's 90% reading, I chose to go with an ArcSwap for synchronization. The memory layout I want to achieve is like so:

stack and heap

I want to use a type like ArcSwap<Arc<[T]>> but the rust compiler is complaining that [T] doesn't implement Sized. This makes sense to me (since it's a slice), but why is it an compile error?

I've looked at the ArcSwap implementation and it seems like the atomic pointer needs to point to a Sized type, but why? (I've copied the definition below)

pub struct ArcSwapAny<T: RefCnt, S: LockStorage = Global> {
    // Notes: AtomicPtr needs Sized
    /// The actual pointer, extracted from the Arc.
    ptr: AtomicPtr<T::Base>,

    /// We are basically an Arc in disguise. Inherit parameters from Arc by pretending to contain
    /// it.
    _phantom_arc: PhantomData<T>,

    lock_storage: S,
}

Is the way to achieve the memory layout ArcSwap<Arc<Box<[T]>>>? That seems very clunky (and I'm worried about triple indirections). Additionally, why does ArcSwap[T; 100] seem to work? What does being a Sized type mean in terms of memory?


Solution

  • For ArcSwap<T> to work, it must be able to swap T atomically. It is possible to swap a pointer atomically, but Arc<[T]> is two pointers wide, and the standard library doesn't provide a cross-platform atomic for that.

    Is the way to achieve the memory layout ArcSwap<Arc<Box<[T]>>>?

    That indeed will be the easiest way.

    What does being a Sized type mean in terms of memory?

    Sized denotes a type that has a size known at compile time. An array, as large as it gets, always has its size known at compile time. A slice not.