libeioのサンプルコード
「libeio」は、C言語で書かれた非同期I/Oライブラリです。
実装的には、キューとスレッドプールを使い、I/Oを非同期並行処理します。
先程の「Boost application performance using asynchronous I/O」の図の右下(Asynchronous + Non-blocking)に「libeio」は位置するのではないかと思います。
- libeioのサンプル
以下、libeioに含まれるdemo.cから抜粋したサンプルです。
#include <stdio.h> #include <stdlib.h> #include <unistd.h> #include <poll.h> #include <string.h> #include <assert.h> #include <fcntl.h> #include <sys/types.h> #include <sys/stat.h> #include "eio.h" int respipe [2]; int last_fd; // EIOスレッドで実行される void want_poll (void) { char dummy; printf ("want_poll ()\n"); write (respipe [1], &dummy, 1); } // EIOスレッドで実行される void done_poll (void) { char dummy; printf ("done_poll ()\n"); read (respipe [0], &dummy, 1); } // mainスレッドのイベントループ void event_loop (void) { struct pollfd pfd; pfd.fd = respipe [0]; pfd.events = POLLIN; printf ("\nentering event loop\n"); while (eio_nreqs ()) { // イベントを待つ poll (&pfd, 1, -1); // mainスレッドでeio_poll()を実行する。 printf ("eio_poll () = %d\n", eio_poll ()); } printf ("leaving event loop\n"); } // mainスレッドで実行される int res_cb (eio_req *req) { printf ("res_cb(%d|%s) = %d\n", req->type, req->data ? req->data : "?", EIO_RESULT (req)); if (req->result < 0) perror(req->errorno); return 0; } // mainスレッドで実行される int read_cb (eio_req *req) { unsigned char *buf = (unsigned char *)EIO_BUF (req); printf ("read_cb = %d (%s)\n", EIO_RESULT (req), buf); return 0; } // mainスレッドで実行される int open_cb (eio_req *req) { printf ("open_cb = %d\n", EIO_RESULT (req)); last_fd = EIO_RESULT (req); return 0; } int main (void) { printf ("pipe ()\n"); if (pipe (respipe)) abort (); printf ("eio_init ()\n"); // libeioにwant_poll()とdone_poll()を登録。 // libeioがpollして欲しいときに、このwant_poll()が呼び出される。 if (eio_init (want_poll, done_poll)) abort (); do { // eio_open()呼び出し後、メインループを実行する。 eio_open ("eio-test-file", O_RDWR | O_CREAT, 0777, 0, open_cb, "open"); event_loop (); // eio_write()呼び出し後、メインループを実行する。 eio_write (last_fd, "aaaaaaaaaa", 10, 0, 0, res_cb, "write"); event_loop (); // eio_read()呼び出し後、メインループを実行する。 eio_read (last_fd, 0, 8, 0, EIO_PRI_DEFAULT, read_cb, "read"); event_loop (); // eio_close()呼び出し後、メインループを実行する。 eio_close (last_fd, 0, res_cb, "close"); event_loop (); } while (0); return 0; }
libeioもlibevと同様に事前にインストールが必要です。libeioのソースコードは、Node.jsのdeps配下にあります。
$ cd libeio $ ./autogen.sh $ ./configure $ make $ make install
- 共有ライブラリのパスに「/usr/local/lib」を追加する。
$ sudo ldconfig
eio-test-fileを作成モードで開き、write(2)とread(2)を実行し、close(2)します。
libeioは、スレッドプールにより並行処理します。mainスレッドとEIOスレッドで通信を行うために、eio_init()で、libeioがpoll通知できるようにします。
mainスレッドから、eio_open()等のeioのI/O関数が呼ばれると、キューにたまります。
EIOスレッドは、キューから取り出して、システムコールを実行し、結果をキューに返して、eio_poll()を呼び出すようmainスレッドに通知します。
mainスレッドがeio_poll()を呼び出すと、事前に設定していた関数がコールバックで呼び出されます。コールバックは、mainスレッドで行われます。