From b17dcd55d724cd9c07e35dec2a2bf5f659ce2de4 Mon Sep 17 00:00:00 2001 From: Ryan Dahl Date: Mon, 28 Mar 2011 03:54:18 -0700 Subject: [PATCH] compiles - obviously doesn't work --- Makefile | 6 +++--- iocp-links.html | 28 ++++++++++++-------------- ol-unix.c | 50 ++++++++++++++++++++++++++++++++++++++++------ ol.h | 3 ++- test/echo-server.c | 1 + 5 files changed, 63 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 1fdd86b8..fb4a84ff 100644 --- a/Makefile +++ b/Makefile @@ -2,7 +2,7 @@ test/echo-server: test/echo-server.c ol.a $(CC) -o test/echo-server test/echo-server.c ol.a -lm ol.a: ol-unix.o ev/ev.o - ar rcs ol.a ol-unix.o ev/ev.o + $(AR) rcs ol.a ol-unix.o ev/ev.o ol-unix.o: ol-unix.c ol.h ol-unix.h $(CC) -c ol-unix.c -o ol-unix.o -lm @@ -17,9 +17,9 @@ ev/config.h: .PHONY: clean distclean clean: - rm *.o *.a + $(RM) -f *.o *.a $(MAKE) -C ev clean distclean: - rm *.o *.a + $(RM) -f *.o *.a $(MAKE) -C ev clean diff --git a/iocp-links.html b/iocp-links.html index c45d3c74..da2b8c27 100644 --- a/iocp-links.html +++ b/iocp-links.html @@ -52,11 +52,9 @@ high-concurrency servers. Instead a system called overlapped I/O is used. I/O - completion ports (IOCP) are the objects used to poll overlapped I/O + completion ports (IOCPs) are the objects used to poll overlapped I/O for completion. - -

-IOCP are similar to the Unix I/O multiplexers +IOCPs are similar to the Unix I/O multiplexers

-The fundamental variation is that in Unixes you generally ask the kernel to +The fundamental variation is that in a Unix you generally ask the kernel to wait for state change in a file descriptor's readability or writablity. With -overlapped I/O and IOCP the programmers waits for asynchronous function +overlapped I/O and IOCPs the programmers waits for asynchronous function calls to complete. For example, instead of waiting for a socket to become writable and then using send(2) -on it, as you commonly do in Unix operating systems, with overlapped I/O you +on it, as you commonly would do in a Unix, with overlapped I/O you would rather WSASend() the data and then wait for it to have been sent. -

Unix non-blocking I/O is not beautiful. A major feature of Unix is the -unified treatment of all things as files (or more precisely as file +

Unix non-blocking I/O is not beautiful. A principle abstraction in Unix +is the unified treatment of many things as files (or more precisely as file descriptors). write(2), read(2), and close(2) work with TCP sockets just as they do on regular files. Well—kind of. Synchronous operations work similarly on different @@ -121,7 +119,7 @@ file descriptors with a I/O multiplexer—not POSIX AIO. Common practice for accessing the disk asynchronously is still done using custom userland thread pools—not POSIX AIO. -

Windows IOCP does support both sockets and regular file I/O which +

Windows IOCPs does support both sockets and regular file I/O which greatly simplifies the handling of disks. Although the function names are not exactly the same in Windows for sockets and regular files, the they act similar. @@ -279,7 +277,7 @@ layer but in the author's opinion, none are completely satisfactory. read(2) calls do not guarantee that they won't block. Therefore libeio is provided for calling various disk-related syscalls in a managed thread pool. Unfortunately the abstraction layer - which libev targets is not appropriate for IOCP—libev works strictly + which libev targets is not appropriate for IOCPs—libev works strictly with file descriptors and does not the concept of a socket. Furthermore users on Unix will be using libeio for file I/O which is not ideal for porting to Windows. On windows libev currently uses @@ -295,14 +293,14 @@ layer but in the author's opinion, none are completely satisfactory. libevent and rejected it—it's interesting to read his reasons why. A - major rewrite was done for version 2 to support Windows IOCP but was done for version 2 to support Windows IOCPs but anecdotal evidence suggests that it is still not working correctly.

Boost ASIO. It basically does what you want on Windows and Unix for - sockets. That is, epoll on Linux, kqueue on Macintosh, IOCP on Windows. + sockets. That is, epoll on Linux, kqueue on Macintosh, IOCPs on Windows. It does not support file I/O. In the author's opinion is it too large for a not extremely difficult problem (~300 files, ~12000 semicolons). diff --git a/ol-unix.c b/ol-unix.c index 0ad0c325..2b7b769a 100644 --- a/ol-unix.c +++ b/ol-unix.c @@ -3,17 +3,16 @@ #include #include #include +#include /* strnlen */ void ol_tcp_io(EV_P_ ev_io* watcher, int revents); void ol_tcp_connect(ol_handle* handle, ol_req* req); +int ol_close_error(ol_handle* handle, ol_err err); static int ol_err_new(int e) { - if (e == 0) { - return e; - } else { - } + return e; } @@ -28,6 +27,16 @@ struct sockaddr_in ol_ip4_addr(char *ip, int port) { } +int ol_close(ol_handle* handle) { + return ol_close_error(handle, 0); +} + + +int ol_run() { + ev_run(0); +} + + ol_handle* ol_handle_new(ol_close_cb close_cb, void* data) { ol_handle *handle = calloc(sizeof(ol_handle), 1); handle->close_cb = close_cb; @@ -65,15 +74,16 @@ int ol_listen(ol_handle* handle, int backlog, ol_accept_cb cb) { } -void ol_close_error(ol_handle* handle, ol_err err) { +int ol_close_error(ol_handle* handle, ol_err err) { ev_io_stop(&handle->_.read_watcher); close(handle->_.fd); handle->_.fd = -1; - if (handle->close_cb) { handle->close_cb(handle, err); } + + return err; } @@ -197,3 +207,31 @@ int ol_connect(ol_handle* handle, ol_req *req_in, struct sockaddr* addr) { return ol_err_new(r); } +int ol_write(ol_handle* handle, ol_req *req, ol_buf* bufs, int bufcnt) { + // stub + assert(0); + return 0; +} + + +int ol_write2(ol_handle* handle, const char* msg) { + size_t len = strnlen(msg, 1024 * 1024); + ol_buf b; + b.base = (char*)msg; + b.len = len; + return ol_write(handle, NULL, &b, 1); +} + + +int ol_read(ol_handle* handle, ol_req *req, ol_buf* bufs, int bufcnt) { + // stub + assert(0); + return 0; +} + + +void ol_free(ol_handle* handle) { + free(handle); + // lists? + return; +} diff --git a/ol.h b/ol.h index bdfa2b4e..b7e32db7 100644 --- a/ol.h +++ b/ol.h @@ -85,6 +85,7 @@ int ol_listen(ol_handle* handle, int backlog, ol_accept_cb cb); int ol_connect(ol_handle* handle, ol_req *req, struct sockaddr* addr); int ol_read(ol_handle* handle, ol_req *req, ol_buf* bufs, int bufcnt); int ol_write(ol_handle* handle, ol_req *req, ol_buf* bufs, int bufcnt); +int ol_write2(ol_handle* handle, const char* msg); int ol_shutdown(ol_handle* handle, ol_req *req); // Request handle to be closed. close_cb will be made @@ -93,7 +94,7 @@ int ol_close(ol_handle* handle); // Must be called for all handles after close_cb. Handles that arrive // via the accept_cb must use ol_free(). -int ol_free(ol_handle* handle); +void ol_free(ol_handle* handle); diff --git a/test/echo-server.c b/test/echo-server.c index 1d12ce4c..96227a44 100644 --- a/test/echo-server.c +++ b/test/echo-server.c @@ -1,6 +1,7 @@ #include "../ol.h" #include #include +#include #define BUFSIZE 1024