-
Notifications
You must be signed in to change notification settings - Fork 15
lep: request all the things #2
base: master
Are you sure you want to change the base?
Conversation
as follows: | ||
|
||
~~~~ | ||
int uv_read(uv_read_t* req, uv_stream_t* handle, uv_buf_t[] bufs, unsigned int nbufs, uv_read_cb, cb) |
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.
Long line.
EDIT: Is there a guideline for that? I would suggest 80 columns.
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.
For now, I kept them between 80 and 100, except the code blocks, but I can fix that.
Some stuff that needs clarification:
A random note about edge triggering: if we ever plan to use edge triggered i/o, we need a good story for |
Depends - it's possible to poll for readable, for some types of streams, most notably TCP connected streams, UDP sockets, and (with some caveats) pipes. Polling for writable is more problematic. Also note that there may be stream types (file streams) for which readable is not a meaningful event. I'd like to get rid of reading with an alloc callback. Instead, I would suggest that we support the poll+try_read pattern for the streams that support it. There should be an API to test whether a particular stream can be polled. This enables the embedder to use that strategy when it's the most efficient, and fall back to uv_read() with a pre-allocated buffer when needed. |
|
||
### A note on uv_cancel | ||
|
||
Gradually, `uv_cancel` needs to be improved to allow for cancelling any kind of requests. |
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.
uv_cancel short-circuits an operation, but the callback still gets called (with ECANCELED as the status). That makes it useful for canceling things that might otherwise take a long time, however it doesn't allow the embedder forget about an operation entirely.
That makes it rather pointless to uv_cancel an uv_callback; the uv_callback never takes a long time so uv_cancel would merely change the status code but not do anything else.
It is not always possible to cancel an operation and also prevent it's callback from executing. But sometimes it is possible - think timers, or -indeed- an uv_callback. We should probably have a separate api for this.
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.
That makes it rather pointless to uv_cancel an uv_callback; the uv_callback never takes a long time so uv_cancel would merely change the status code but not do anything else.
You're right, I'm not sure what I was thinking here...
It is not always possible to cancel an operation and also prevent it's callback from executing. But sometimes it is possible - think timers, or -indeed- an uv_callback. We should probably have a separate api for this.
I think we could leave the API we have for uv_cancel like it is, for now. For timers, it does make sense to be able to cancel them, and the callback would be called with status == UV_ECANCELED, so you know it didn't actually kick in.
Ideally it would be nice to avoid getting the callback called with UV_ECANCELLED in case uv_cancel returned "true", but I'm not sure this can be done in all cases.
That's not quite what I meant but I didn't phrase it very well. My thinking was that we should be able to implement uv_read() in terms of uv_stream_poll() + uv_alloc_cb() + uv_try_read(); ditto for uv_write().
I like that. |
Agreed. I guess that the return code from uv_stream_poll could be used for that: if it returns ENOTSUP, you would fallback. |
- Remove note on uv_cancel - Remove uv_try_read - Remove uv_read_alloc - uv_read with NULL callback == former uv_try_read - Clarified that uv_callback requests cannot be cancelled - Removed status from uv_callback's callback - Clarify when timers can fail
Added another round of fixes, please take a look when you can. Thanks! |
LGTM |
pass a `uv_buf_t` array which is allocated on the stack, as long as the memory in each `buf->base` | ||
is valid until the request callback is called. | ||
|
||
Inline reading: if the passed callback `cb` is NULL and there are no more queued read requests |
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 think I disagree. We should not define the "meaning" of omitting a callback arbirtrarily. Instead I'd prefer to use a generic pattern.
The uv_fs_xx class of functions also allows you to omit the callback. There it means that the operation should be blocking.
uv_close() allows one to omit the callback. There it means that the operation is still asynchronous but no callback gets called.
My preference is to say that passing no callback to an async function means "blocking".
In addition, what's weird is that in the case of uv_write() the semantic of the function also changes subtly. Whereas the async version of uv_write() would always write the entire buffer, the "try" variant would only write as much bytes as it could.
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.
Right, we would be inconsistent there. How about passing a NULL request instead? Alternatively we could keep the uv_try_* variants instead of foldling the functionality into a single API function.
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.
Thoughts on the above, Bert?
Hi, What you might want for the async read operation is to request it to either callback once any data is received or only when exactly the required amount of data is received. Afaik polling for read readiness on windows can be done by starting asynchronous 0-byte read operations with IOCP. |
uv_stream_t* handle, | ||
const uv_buf_t[] bufs, | ||
unsigned int nbufs, | ||
uv_read_cb, cb) |
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.
typo?
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.
Yes :-)
@Matthias247 yes, it will be covered. Maybe not exactly using a NULL callback, put the possibility will be there. We are ironing out API details. |
@trevnorris thanks for the feedback, pushed some fixes. |
@saghul What's the status of this proposal? Is it dead? |
It is still a goal of mine, but this plan was too ambitious and too many things will break. So we are taking smaller steps. Also, we found some bumps on the way and some of the devs (myself, for one) have less time these days to work on it. |
@saghul I'm interested in pull based reads. I saw that was planned for 2.0 and this was the only thing I could find with details. Just FYI, I work for Microsoft on the ASP.NET Core team and we own a web server with a libuv based transport (https://github.com/aspnet/KestrelHttpServer). |
@davidfowl I did at one point experiment with wrapping existing libuv with a C layer that exposed it as pull based. I never could get it very efficient, but depending on your requirements and scope, something like that might work. I wanted pull based since luajit's FFI doesn't do well with C callbacks. |
No description provided.