Rust really made me appreciate garbage collection after the number of times I resorted to things like Arc<Box<..>>.
Rust really made me appreciate garbage collection after the number of times I resorted to things like Arc<Box<..>>.
However they are obsessed about performance. They reason for such speedy compile times is that makepad almost has no dependencies.
Folks at makepad poured enormous effort in keeping dependency graph minimal.
... What are you doing ? It's definitively unusual.
No it's not, it's extremely common. `Arc<Box<...>>` or `Arc<Mutex<Box<...>>>` or similar is used all the time when you want to share a mutable reference (on the heap, in the case of Box); especially in the case of interior mutability[1]. It's pretty annoying, but I have learned to love the borrow checker (although lifetime rules still confuse me). It really does make my code extremely clear, knowing exactly what parts of every struct is shareable (Arc) & mutable (Mutex).
[1] https://doc.rust-lang.org/book/ch15-05-interior-mutability.h...
Arc-Mutex yes, Arc-Box no.
It's like "I want a shared, immutable reference to something recursive, or unsized". The heap part makes no sense because it's already allocated there if you use an Arc : https://doc.rust-lang.org/std/sync/struct.Arc.html
> The type Arc<T> provides shared ownership of a value of type T, allocated in the heap.
Moreover, you don't even need the box for a dyn : https://gist.github.com/rust-play/f19567f8ad4cc00e3ef17ae6b3...
Yeah, looks like Arc-Box is kind of pointless, but isn't there some thread locality reason why people wrap `Box` in `Arc`? I remember reading something about it a while ago but maybe I'm misremembering.
`Arc<T>` places the refcounts immediately before `T` in memory. If you are desperate to have `T` and `T`'s refcounts be on different cachelines to reduce false sharing in some contrived scenario, `Arc<Box<T>>` would technically accomplish this. I think a more realistic optimization would be to pad the start of `T` however.
`Box<Box<T>>` and `Arc<Box<T>>` are thin pointers (size ≈ size_of::<usize>()) even when `Box<T>` is a fat pointer (size ≈ 2*size_of::<usize>() because `T` is `str`, `[u8]`, `dyn SomeTrait`, etc.). While various "thin" crates are typically saner alternatives for FFI or memory density (prefixing lengths/vtables in the pointed-at data instead of incurring double-indirection and double-allocation), these double boxes are a quick and dirty way of accomplishing guaranteed thin pointers with only `std` / `alloc`.
I would not call either of these use cases "extremely common" however.