Async-std, splitting reader/writer & lifetimes

I have a function that handles incoming connections and it looks sort-of like this:

async fn connection_loop(stream: TcpStream,
      jobq: Arc<Mutex<JobQueue>>) -> Result<()> {
  let reader = io::BufReader::new(&stream);
  let mut lines = reader.lines();

  let writer = io::BufWriter::new(&stream);
  let writer = Arc::new(Mutex::new(writer));

  while let Some(line) = {
    let line = line?;

    // parse line

    // Add jobespec on to queue
    let mut jq = jobq.lock().await;

    let jobspec = Job { pathname: std::path::PathBuf::from(fname), alg,
      id: id.to_string() };

    if jq.q.len() < jq.max_jobs {
      if let Some(n) = jq.q.pop_back() {
        let id =;
        let pathname = n.pathname.clone();
        let fut = hasher(id, pathname, Arc::clone(&writer));


The idea is that the connection_loop function is the only one that'll read from the stream, and the hasher futures are the only ones that'll write to the stream (though there may be several hasher future instances). I assumed the lifetimes are broken (the BufReader/Writer objects may outlive stream), and indeed I get an error:

error[E0597]: `stream` does not live long enough
   --> src/
76  |   let writer = io::BufWriter::new(&stream);
    |                -------------------^^^^^^^-
    |                |                  |
    |                |                  borrowed value does not live long enough
    |                argument requires that `stream` is borrowed for `'static`
118 | }
    | - `stream` dropped here while still borrowed

What's a good/common/idiomatic pattern to make sure that the stream lives on for as long as it needs to?

Usually there's some way to split the tcp stream into a reader and writer pair, but I can't find it in async_std.

1 Like

Ah, so it would essentially consume the stream object?

I switched from async-std to tokio, which solved this issue.