-2

I have a dynamic number of "streams" (it's actually a Quinn crate RecvStream that doesn't implement the Copy trait) and I call this code on it:

let fut = stream.read(&mut buffer);
streams.push(fut);

The buffer is a simple &[u8] and the streams is my instance of a futures::FuturesUnordered.

This is great and I can use a Tokio select! macro on streams.next(). But I only get the number of bytes read back with no association with the data buffer and RecvStream instance. This means I cannot reissue the read operation to grab the next batch of data.

I've tried wrapping the future with another future that contains the stream and buffer who's associated type Output is a tuple of its contents but have run into pinning issues. I was hoping this outer future could be pushed on to the FuturesUnordered and I would have the stream and buffer to call read() again and re-push.

Can anyone offer advice on how I should architect a solution where I retain the result of the future and the original association of the structures that created it in the first place?

Chayim Friedman
  • 47,971
  • 5
  • 48
  • 77
Cthutu
  • 8,713
  • 7
  • 33
  • 49
  • 2
    Instead of having partial futures that you requeue, just use a single future for the whole task: e.g. `let fut = async move { while !done() { let bytes = stream.read (&mut buffer).await; /* do something with the buffer */ }};` – Jmb May 30 '23 at 14:43
  • That would be inefficient as earlier streams will block later streams while they're waiting for data. The number of incoming streams vary as users join and leave. – Cthutu May 30 '23 at 15:24
  • 2
    No they wouldn't, that's the whole point of `FuturesUnordered` or `select!`: they drive all the futures _in parallel_ until one of them completes. – Jmb May 30 '23 at 17:28
  • I forgot I could create a future with a simple async block. I was trying to implement the Future trait and other dumb crap like that :) – Cthutu May 30 '23 at 19:00

0 Answers0