-
Notifications
You must be signed in to change notification settings - Fork 641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
feat(futures-util/stream): implement stream.unzip adapter #2256
Conversation
I want to add some tests though, but not sure where to add them, since tests for example for adaptor |
/// SAFETY: safe because only one of two unzipped streams is guaranteed | ||
/// to be accessing underlying stream. This is guaranteed by mpsc. Right | ||
/// stream will access underlying stream only if Sender (or left stream) | ||
/// is dropped in which case try_recv returns disconnected error. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't think this is correct. You can call UnzipLeft(Right)::poll_next
and UnzipRight(Left)::is_terminated
at the same time.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Oh right! But I can simply maintain is_done
boolean in UnzipRight
and set it to true
if I receive Poll::Ready(None)
right? For example Fuse<S>
seems to do the same.
Or is there a case when: is_terminated()
returns true for underline stream but it still hasn't emitted Poll::Ready(None)
and won't ever emit it?
If thats the case, would UnzipLeft
be dropped if it is_terminated
? So would it be sufficient if is_terminated()
returned:
is_done
if left is not dropped.stream.is_terminated()
if left is dropped, since it's now safe to call that method.
Given that
I recommend adding to |
Thanks! Will add tests there.
Hm... If I understand this right, you mean that unzip should not separate streams, but I didn't quite get the alternative. What would the api look like for the unzip that you are talking about? What do you suggest I do with the code? Should I change it into |
`UnzipRight::is_terminated(&self)` was accessing base stream, which should **never** happen, unless left is dropped. As a fix, manually maintain `is_done` field.
The way this works is by putting the base stream in the
Arc
and sharing thatArc
inUnzipLeft
andUnzipRight
streams.Initially only
UnzipLeft
is polling the base stream, emits first tuple item as it's result and sends the other one throughmpsc::channel
to theUnzipRight
. At the end of the stream,UnzipLeft
sendsPoll::Ready(None)
through the channel to left theUnzipRight
know stream is finished.UnzipLeft
is dropped, first it dropsmpsc::Sender
and then wakes up theUnzipRight
task, which is a way of telling toUnzipRight
to take over polling the base stream (Sincetry_recv
called by right stream will error withTryRecvError::Disconnected
if sender is dropped).UnzipRight
is dropped,right_waker.upgrade()
will fail and returnNone
sinceright_waker
is aWeak
type ofArc
. If that happens, send simply won't happen.There is unsafe code when converting base stream from
Pin<&mut Arc<Stream>>
toPin<&mut Stream>
in order to poll it, but since we are accessing base stream only from one of the streams at a time, it's safe right?closes: #2234