multithreadingrustgame-theorymud

Rust syncronization strategy for MUD server


So if you had a MUD sever that handled each tcp connection in a separate process,

for stream in acceptor.incoming() {
    match stream {
        Err(e) => { /* connection failed */ }
        Ok(stream) => spawn(proc() {
            handle_client(stream)
        })
    }
}

What would be the strategy for sharing mutable world data for that server? I can imagine n connections responding to commands from the user. Each command needing to visit and possibly modify the world.

pub struct Server<'a> {
    world: World<'a>
}

pub struct World<'a> {
    pub chat_rooms: HashMap<&'a str, ChatRoom<'a>>
}


impl<'a> World<'a> {
    pub fn new() -> World<'a> {
        let mut rooms = HashMap::new();
        rooms.insert("General", ChatRoom::new("General"));
        rooms.insert("Help", ChatRoom::new("Help"));
        World{chat_rooms: rooms}
    }
}

Would Arc be the way to go?

let shared_server = Arc::new(server);
let server = shared_server.clone();

spawn(proc() {
    // Work with server
});

What about scaling to 100 or 1000 users? I'm just looking for a nudge in the right direction.


Solution

  • An Arc will let you access a value from multiple tasks, but it will not allow you to borrow the value mutably. The compiler cannot verify statically that only one task would borrow the value mutably at a time, and mutating a value concurrently on different tasks leads to data races.

    Rust's standard library provides some types that allow mutating a shared object safely. Here are two of them:

    You'll need to wrap a Mutex or a RWLock in an Arc to make it accessible to multiple tasks.