libuv

The little library that could

July 2nd, 2012





Node 0.5.x

libev

  • Wrapper around select() and more scalable counterparts (epoll, kqueue, ...)
  • ev_io -> data ready to be read.
  • ev_io -> good time to write data.

libeio

  • Thread pool
  • Convenience methods for file operations

Implicit assumptions

Windows Many people think windows support was the primary reason for building libuv. But that's not the whole story. When work on libuv started node was already mostly working on windows and part of the fast IOCP backend was also ready. The reason to put it all in libuv was to make node's platform code more manageable. * Press any key to continue. * Press CTRL+ALT+RESET to restart your computer. You will lose any unsaved information in all applications Press any key to continue

libuv

require('net').connect(80, 'nyan.cat').pipe(process.stdout);
int main(int argc, char* argv[]) {
  uv_getaddrinfo_t* gai_req = malloc(sizeof(uv_getaddrinfo_t));

  uv_getaddrinfo(uv_default_loop(),
                 gai_req,
                 after_getaddrinfo,
                 "nyan.cat",
                 "80",
                 NULL);

  uv_run(uv_default_loop());

  return 0;
}
 void after_getaddrinfo(uv_getaddrinfo_t* gai_req, int status,
    struct addrinfo* ai) {
  uv_tcp_t* tcp_handle;
  uv_connect_t* connect_req;

  if (status < 0)
    abort(); /* handle error */

  tcp_handle = malloc(sizeof(uv_tcp_t));
  uv_tcp_init(uv_default_loop(), tcp_handle);

  connect_req = malloc(sizeof(uv_connect_t));
  uv_tcp_connect(connect_req,
                 tcp_handle,
                 *(struct sockaddr_in*) ai->ai_addr,
                 after_connect);

  free(gai_req);
  uv_freeaddrinfo(ai);
}
void after_connect(uv_connect_t* connect_req, int status) {
  uv_write_t* write_req;
  uv_buf_t buf;

  if (status < 0)
     abort(); /* handle error */

  write_req = malloc(sizeof(uv_write_t));

  buf.base = "GET / HTTP/1.0\r\n"
             "Host: nyan.cat\r\n"
             "\r\n";
  buf.len = strlen(buf.base);

  uv_write(write_req, connect_req->handle, &buf, 1, after_write);

  uv_read_start(connect_req->handle, on_alloc, on_read);

  free(connect_req);
}
uv_buf_t on_alloc(uv_handle_t* handle, size_t suggested_size) {
  uv_buf_t buf;

  buf.base = malloc(suggested_size);
  buf.len = suggested_size;

  return buf;
}
void on_read(uv_stream_t* tcp_handle, ssize_t nread, uv_buf_t buf) {
  if (nread < 0) {
    /* Error or end of file */
    if (uv_last_error(uv_default_loop()).code == UV_EOF) {
      /* No more data. Close the connection. */
      uv_close((uv_handle_t*) tcp_handle, on_close);
    } else {
      /* That's an error. */
      abort();
    }
  }

  if (nread > 0) {
    /* Print it! FTW!!!1 */
    fwrite(buf.base, 1, nread, stdout);
  }

  free(buf.base);
}
void on_close(uv_handle_t* handle) {
  free(handle);
}
piscisaureus@pub:~/libuv$
piscisaureus@pub:~/libuv$ gcc -o demo demo.c uv.a -Iinclude -lpthread -lm -lrt
piscisaureus@pub:~/libuv$
piscisaureus@pub:~/libuv$ ./demo
HTTP/1.1 200 OK
Date: Sun, 01 Jul 2012 07:44:46 GMT
Server: Apache
X-Powered-By: PHP/5.2.17
Connection: close
Content-Type: text/html

<!DOCTYPE html>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<div id='title'>
        <title> NYAN.CAT! </title>
</div>
<div id="css">
        <link type="text/css" rel="stylesheet" media="screen" href="css/original.css"/>
</div>
<script type="text/javascript" src="code/jquery-1.6.4.js"></script>
<script type="text/javascript" src="languages/original.js"></script>
<script type="text/javascript" src="code/soundmanager2.js"></script>
<script type="text/javascript" src="code/snow.js"></script>
<script type="text/javascript" src="http://konami-js.googlecode.com/svn/trunk/konami.js"></script>
<script type="text/javascript">
        konami = new Konami()
        konami.load("javascript:showsnow()");
</script>
<style type="text/css">
       #flavors { background:rgba(0,0,0,0.35); float:right; display:none; text-align:center;border-radius: 15px; }
           @-moz-document url-prefix() {.banner{z-index:-2;width:100%;}}
           .banner{z-index:-2;position:absolute;width:100%;}</style>
<link rel="icon" href="favicon.ico" type="image/x-icon">
<link rel="shortcut icon" href="favicon.ico" type="image/x-icon">
<script type="text/javascript" src="code/misc.js"></script>
<script type="text/javascript">
// <![CDATA[
if ((navigator.userAgent.indexOf('iPhone') != -1) ||(screen.width <=699) || (navigator.userAgent.indexOf('iPod') != -1) || (navigator.userAgent.indexOf('iPad')
!= -1)) { document.location = "mobile.php"; } // ]]>
</script>
<script type="text/javascript">
       startVolume = 50

So what can libuv do for you?

The future

Past node

Thank you!

https://github.com/joyent/libuv