1
votes

I'm writing an application that uses a Distributed Hashtable (DHT) to distribute data to various nodes. When inserting data, I have to loop through it all and write various parts to different nodes. Instead of opening a new TcpStream object for each write, I would like to maintain a map of streams that I can use to write the data as needed. I'm very new to the Rust language and I'm having issues with lifetimes, specifically the errors

cannot borrow 'streams' as mutable because it is already borrowed as mutable

'stream' does not live long enough.

I'm sure there is a fancy Rust way of doing this. The code I'm working with is below.

let mut streams = HashMap::new();
...
//get socket address to send data too
loop {
    match streams.get(&socket_addr) {
        Some(stream) => {
             capnp::serialize::write_message(*stream, &msg_builder).unwrap();
        },
        None => {
             let mut stream = TcpStream::connect(socket_addr).unwrap();
             streams.insert(socket_addr, &mut stream);
             capnp::serialize::write_message(&mut stream, &msg_builder).unwrap();
        }
    }
}
1
Welcome to Stack Overflow! It is frowned upon to ask multiple questions in one post. Additionally, your questions have already been asked. The "does not live long enough" could be stackoverflow.com/q/31775915/155423, and "already borrowed as mutable" could be stackoverflow.com/q/28512394/155423. Please search for duplicates before asking a question, and then describe why your question is different from the previous questions if you decide it's not a duplicate.Shepmaster

1 Answers

3
votes

You cannot insert a reference to the stream in the HashMap, since the stream is a local variable that goes out of scope at the end of the match expression. The HashMap must own the stream.

The easiest way to implement this is using the entry() method on HashMap to open the stream at first use.

fn main() {
    let socket_addr = /* ... */;
    let mut streams = HashMap::new();
    let msg_builder = /* ... */;
    loop {
        let stream = streams.entry(&socket_addr).or_insert_with(|| {
            TcpStream::connect(socket_addr).unwrap()
        });
        capnp::serialize::write_message(stream, &msg_builder).unwrap();
    }
}