Skip to content

Instantly share code, notes, and snippets.

@saghul
Last active August 29, 2015 14:03
Show Gist options
  • Save saghul/909502cc7367a25c247a to your computer and use it in GitHub Desktop.
Save saghul/909502cc7367a25c247a to your computer and use it in GitHub Desktop.

RFC: Replace uv_sread_start/stop with uv_read

Overview

This proposal aims to replace the current functions to start and stop reading data from a stream in a push-fashion with a uv_read function which would work in a pull-fashion. Function prototype:

typedef void (*uv_read_cb)(uv_read_t* req, int status);

UV_EXTERN int uv_read(uv_read_t* req,
                      uv_stream_t* handle,
                      const uv_buf_t bufs[],
                      unsigned int nbufs,
                      uv_read_cb cb);

How it works

Basically this would work as an async readv. Once the read operation is completed the callback would be fired and the status parameter would contain the number of bytes read, or an error. Support for cancellation of this type of requests is also planned.

Reasoning

  • Consistency with write operations
  • A push style API can be emulated on top of this pull style API by having a request active all the time and rearming it after a read is performed, but not the other way around. It's doable, but more cumbersome.
  • It could poptentially simplify how memory is managed for reading, as it's attached to each request and the user is responsible for allocating any buffer size, which needs to be valid until the request callback is called.
  • Wisdom of hindsight by @bnoordhuis: joyent/libuv#1246 (comment)

Windows

Funny enough, Windows already works like this internally.

RFC: Replace uv_sread_start/stop with uv_read

Overview

This proposal aims to replace the current functions to start and stop reading data from a stream in a push-fashion with a uv_read function which would work in a pull-fashion. Function prototype:

typedef void (*uv_read_cb)(uv_read_t* req, int status);

UV_EXTERN int uv_read(uv_read_t* req,
                      uv_stream_t* handle,
                      uv_alloc_cb alloc_cb,
                      uv_read_cb read_cb);

How it works

Basically this would work as an async read. When the fd is ready for reading the alloc_cb callback is called and the user needs to supply a buffer. A suggested size of 64K is still provided. Once the read operation is completed the callback would be fired and the status parameter would contain the number of bytes read, or an error. Support for cancellation of this type of requests is also planned.

Reasoning

  • Consistency with write operations
  • A push style API can be emulated on top of this pull style API by having a request active all the time and rearming it after a read is performed, but not the other way around. It's doable, but more cumbersome.
  • It could poptentially simplify how memory is managed for reading, as it's attached to each request and the user is responsible for allocating any buffer size, which needs to be valid until the request callback is called.
  • Wisdom of hindsight by @bnoordhuis: joyent/libuv#1246 (comment)

Discussion

https://groups.google.com/forum/#!topic/libuv/irHB6Agnulw

@piscisaureus
Copy link

Funny enough, Windows already works like this internally.

It is the "iocp model". However in case of tcp we do some trickery to avoid it. Otherwise you need to pre-allocate x kb (typically 64 kb) per socket; so when there are many open-but-mostly-idle connections such as websockets, this uses up a lot of memory for no gain.

@saghul
Copy link
Author

saghul commented Jul 1, 2014

Thanks for the pointer Bert!

@txdv
Copy link

txdv commented Jul 1, 2014

A question about windows: Is it more efficient to always have another read queued while one is being already processed?

@txdv
Copy link

txdv commented Jul 1, 2014

Why the hell do you have two files? The very idea of git should mitigate the need for this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment