Skip to content
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

Design Core Interface that wraps libuv #2

Open
creationix opened this issue Jun 2, 2016 · 3 comments
Open

Design Core Interface that wraps libuv #2

creationix opened this issue Jun 2, 2016 · 3 comments

Comments

@creationix
Copy link
Member

creationix commented Jun 2, 2016

This task is to design the interface that wraps libuv and exposes it to JavaScript. This should be as minimal as possible while still feeling like natural JavaScript and not C.

For example, in libuv, there is a hierarchy of structs that act like classes with inheritance. In JS, we can use prototype chains for the uv_tcp_t methods that inherits from uv_stream_t methods that inherits from uv_handle_t methods.

All libuv functions are plain C functions. There are no classes. The ones that act like methods accept the struct as the first argument. In luv, I exposed these in both ways.

For example, here is a sample TCP echo server in plain luv.

local uv = require('uv')

local server = uv.new_tcp()
server:bind("127.0.0.1", 1337)
server:listen(128, function (err)
  assert(not err, err)
  local client = uv.new_tcp()
  server:accept(client)
  client:read_start(function (err, chunk)
    assert(not err, err)
    if chunk then
      client:write(chunk)
    else
      client:shutdown()
      client:close()
    end
  end)
end)
print("TCP server listening at 127.0.0.1 port 1337")
uv.run()

In lua, there are no methods per-se, but the obj:name(...) syntax means to callobj.name(obj, ...) injecting the thing to the left of the colon as the first argument. In JS, we have this which can be used in a similar way.

var uv = require('uv');

var server = new uv.Tcp();
server.bind("127.0.0.1", 1337);
server.listen(128, function (err) {
  if (err) throw err;
  var client = new uv.Tcp();
  server.accept(client);
  client.read_start(function (err, chunk) {
    if (err) throw err;
    if (chunk) {
      client.write(chunk);
    }
    else {
      client.shutdown();
      client.close();
    }
  });
});
print("TCP server listening at 127.0.0.1 port 1337");
uv.run();
@creationix
Copy link
Member Author

You can see the general libuv shape in the luv docs and libuv's docs

@creationix
Copy link
Member Author

new uv.Tcp(flags) -> uv_tcp_t

Create a new uv_tcp_t instance. This will inherit from uv.Tcp.prototype which inherits from uv.Stream.prototype which inherits from uv.Handle.prototype.

If flags is not set, uv_tcp_init is used, if it is set, uv_tcp_init_ex is used passing the flags through.

Below when tcp.* is used, it means uv.Tcp.prototype which become methods on the tcp instance.

tcp.open(fd)

Open an existing file descriptor or SOCKET as a TCP handle.

The file descriptor is set to non-blocking mode.

tcp.nodelay(enable)

Enable / disable Nagle’s algorithm.

tcp.keepalive(enable, delay)

Enable / disable simultaneous asynchronous accept requests that are queued by the operating system when listening for new TCP connections.

This setting is used to tune a TCP server for the desired performance. Having simultaneous accepts can significantly improve the rate of accepting connections (which is why it is enabled by default) but may lead to uneven load distribution in multi-process setups.

...

@creationix
Copy link
Member Author

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant