Is there an alternative to Arc<Mutex<T>> spam for multithreading?

108 points endistic 75 comments

o/

For context, I'm working on a Minecraft Server Library implementation in Rust.
Full source code: https://github.com/akarahdev/wyvern-mc

However, I am experiencing a code pattern that I am pretty sure is bad, but I don't know what else to do.

All over my codebase is Arc<Mutex<T>> or similar of various structures.

For examples:

#[derive(Clone)]
pub struct Dimension {
    pub(crate) inner: Arc<Mutex<DimensionData>>
}

#[derive(Clone)]
pub struct Entity {
    pub(crate) inner: Arc<Mutex<EntityData>>
}

#[derive(Clone)]
pub struct Server {
    pub(crate) inner: Arc<ServerData>,
}


#[derive(Clone)]
pub struct Player {
    pub(crate) inner: Arc<ConnectionData>,
    pub(crate) server: Server,
    pub(crate) packet_sender: Sender<PacketBuf>,
}

(The Player struct technically leaks memory right now as Arc is never deallocated, but I will fix that eventually, so don't mind that.)

The ones above that aren't wrapped in Mutex<T> have more finegrained locks inside of the structures.

One of Rust's big advantages is the borrow checker. The thing is, Arc<Mutex<T>> spam basically completely disregards the borrow checker and similar. It also basically turns Rust into a garbage-collected programming language, which I would like to avoid if possible.

Is there a more ergonomic / better way of doing this?

I think I should also mention that my codebase is currently not async, but I'm hoping to eventually migrate it to be based on async Rust & Tokio instead.

Thank you for the help. :)