简体   繁体   中英

How to take a subslice of an Arc<[T]>

fn subslice(a: Arc<[T]>, begin: usize, end: usize) -> Arc<[T]> {
    Arc::new(a[begin..end])
}

The above "obvious implementation" of the subslicing operation for Arc<[T]> does not work because a[begin..end] has type [T] , which is unsized. Arc<T> has the curious property that the type itself does not require T: Sized , but the constructor Arc::new does, so I'm at a loss for how to construct this subslice.

You can't.

To explain why, let's look at what Arc actually is under the covers.

pub struct Arc<T: ?Sized> {
    ptr: Shared<ArcInner<T>>,
}

Shared<T> is an internal wrapper type that essentially amounts to " *const T , but can't be zero"; so it's basically a &T without a lifetime. This means that you can't adjust the slice at this level; if you did, you'd end up trying to point to an ArcInner that doesn't exist. Thus, if this is possible, it must involve some manipulation of the ArcInner .

ArcInner<T> is defined as follows:

struct ArcInner<T: ?Sized> {
    strong: atomic::AtomicUsize,
    weak: atomic::AtomicUsize,
    data: T,
}

strong and weak are just the number of strong and weak handles to this allocation respectively. data is the actual contents of the allocation, stored inline. And that's the problem.

In order for your code to work as you want, Arc would not only have to refer to data by another pointer (rather than storing it inline), but it would also have to store the reference counts and data in different places, so that you could take a slice of the data, but retain the same reference counts.

So you can't do what you're asking.


One thing you can do instead is to store the slicing information alongside the Arc . The owning_ref crate has an example that does exactly this .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM