I have a few public types that implement AsyncRead/Write, but I haven't looked at vectored IO yet. I read sometimes that it's bad that people forget to implement these methods because default impls are provided.
Unfortunately, the docs on futures lib don't tell you that and even less when it's appropriate to implement them.
As an example. I put AsyncRead/AsyncWrite on top of websockets.
In my WsStream, I use an algorithm taken from futures::IntoAsyncRead
. Note that futures::IntoAsyncRead
doesn't implement poll_read_vectored
.
I buffer up to one websocket message. In poll_read
, I try to get a message out of the underlying stream if I don't have one. Then I try to copy as much of it as I can into the buffer I got. I keep track of how far we read into the message in case it didn't fit entirely, then next time we will fit the rest.
However if the buffer is bigger than the message, currently I just don't fill it entirely (same as futures::IntoAsyncRead
). So the first question is, should I poll the stream for the next message, knowing that it might just return pending, and that we cannot return pending here (as we already filled part of the buffer), so it will wake up the task even though we didn't return pending in poll_read
.
Is such a spurious wakup a problem? Maybe just call with a dummy waker when we already have data to return?
Secondly then should I implement poll_read_vectored
for this? I suppose I could fill several buffers, instead of just filling the first one like the default impl does, but that means either:
- only do that when the ws message is to big to fit in the first buffer
- solving the
poll_read
question above so that we can fill the buffers with data from several websocket messages? If it is fine to have spurious wakeups, why does the default impl not callpoll_read
several times in order to fill up all the buffers untilpoll_read
returns pending? It could also do something like the dummy waker.
For poll_write_vector
, the implementation itself is simpler. The websocket api just wants a Vec<u8>
for the websocket message, so I could just allocate one big enough for the total of all vectors passed in and copy all the data in there.
So is it appropriate for such a layer on websockets to implement poll_write_vectored
even though the actual networking layer doesn't really do vectored IO and I will copy all buffers into one Vec
?