Commit ddfa2d41d2bc1db77689ffc8eb53b1286da80151

Thomas de Grivel 2018-06-16T14:18:49

thot-simple -> thot-select

diff --git a/README b/README
index ffc1e8d..7219d25 100644
--- a/README
+++ b/README
@@ -1,6 +1,14 @@
+Threaded HTTP server supporting EPOLL in Common Lisp
 
-(asdf:load-system :thot)
+Thot has the following acceptor loops :
+    epoll  unthreaded, using epoll(7) on Linux
+   select  unthreaded, using select(2)
+ threaded  threaded defaults to 8 threads, see *INIT-THREADS*
 
-(thot:start)
+The threaded loop has the following worker loops :
+    epoll  using epoll(7) on Linux
+   select  using select(2)
 
-(thot:start :port 8000)
+Usage :
+    (asdf:load-system :thot)
+    (thot:start)
diff --git a/thot-select.lisp b/thot-select.lisp
new file mode 100644
index 0000000..0660be2
--- /dev/null
+++ b/thot-select.lisp
@@ -0,0 +1,61 @@
+;;
+;;  Thot - http web server
+;;  Copyright 2017,2018 Thomas de Grivel <thoxdg@gmail.com> 0614550127
+;;
+
+(in-package :thot)
+
+(defun request-loop-simple (request-stream reply-stream)
+  (loop
+     (when *stop*
+       (return))
+     (handler-case
+         (let* ((req (make-instance 'request :stream request-stream))
+                (reply (make-instance 'reply :stream reply-stream))
+                (reader (request-reader req reply))
+                (result (funcall (the function reader))))
+           (unless (eq :keep-alive result)
+             (return)))
+       (warning (w)
+         (msg warn w)
+         (continue))
+       (error (e)
+         (msg error e)
+         (return)))))
+
+(defun fd= (a b)
+  (= (the unistd:file-descriptor a) (the unistd:file-descriptor b)))
+
+(defun acceptor-loop-select (fd &optional pipe)
+  (declare (type unistd:file-descriptor fd))
+  (let ((readfds))
+    (push fd readfds)
+    (when pipe
+      (push (the unistd:file-descriptor pipe) readfds))
+    (loop
+       (when *stop*
+         (return))
+       (unistd:with-selected (readfds () () 100)
+           (readable writable errors)
+         (when (and pipe
+                    (find pipe readable :test #'fd=))
+           (return))
+         (when (find fd readable :test #'fd=)
+           (socket:with-accept (clientfd) fd
+             (let ((request-stream
+                    (babel-input-stream
+                     (unistd-input-stream clientfd)))
+                   (reply-stream
+                    (babel-output-stream
+                     (multi-buffered-output-stream
+                      (unistd-output-stream clientfd)))))
+               (request-loop-simple request-stream
+                                    reply-stream))))))))
+
+(defun configure-select ()
+  (setf *acceptor-loop* #'acceptor-loop-select))
+
+(eval-when (:load-toplevel :execute)
+  (configure-select))
+
+;(trace acceptor-loop-select request-loop-simple cffi-socket:accept unistd:write stream-flush stream-flush-output unistd:close)
diff --git a/thot-simple.lisp b/thot-simple.lisp
deleted file mode 100644
index 3b8ae47..0000000
--- a/thot-simple.lisp
+++ /dev/null
@@ -1,38 +0,0 @@
-;;
-;;  Thot - http web server
-;;  Copyright 2017,2018 Thomas de Grivel <thoxdg@gmail.com> 0614550127
-;;
-
-(in-package :thot)
-
-(defun acceptor-loop-simple (fd &optional pipe)
-  (declare (type (unsigned-byte 31) fd))
-  (let ((readfds))
-    (push fd readfds)
-    (when pipe
-      (push pipe readfds))
-    (labels ((acceptor-loop-simple-fun ()
-               (loop
-                  (when *stop*
-                    (return))
-                  (unistd:with-selected (readfds () () 100)
-                      (readable writable errors)
-                    (when (and pipe (find pipe readable))
-                      (return))
-                    (when (find fd readable)
-                      (socket:with-accept (clientfd) fd
-                        (let ((request-stream
-                               (babel-input-stream
-                                (unistd-input-stream clientfd)))
-                              (reply-stream
-                               (babel-output-stream
-                                (multi-buffered-output-stream
-                                 (unistd-output-stream clientfd)))))
-                          (request-loop request-stream
-                                        reply-stream))))))))
-      #'acceptor-loop-simple-fun)))
-
-(eval-when (:load-toplevel :execute)
-  (setq *acceptor-loop* 'acceptor-loop-simple))
-
-;(trace acceptor-loop-simple request-loop cffi-socket:accept unistd:write stream-flush stream-flush-output unistd:close)
diff --git a/thot.asd b/thot.asd
index 70a829d..482b7cc 100644
--- a/thot.asd
+++ b/thot.asd
@@ -30,6 +30,6 @@
   ((:file "package")
    (:file "mime" :depends-on ("package"))
    (:file "thot" :depends-on ("mime"))
-   (:file "thot-simple" :depends-on ("thot"))
-   (:file "thot-threaded" :depends-on ("thot-simple"))
-   #+linux (:file "thot-epoll" :depends-on ("thot-threaded"))))
+   (:file "thot-select" :depends-on ("thot"))
+   (:file "thot-threaded" :depends-on ("thot"))
+   #+linux (:file "thot-epoll" :depends-on ("thot"))))
diff --git a/thot.lisp b/thot.lisp
index 227984d..fcc7f09 100644
--- a/thot.lisp
+++ b/thot.lisp
@@ -552,22 +552,6 @@ The requested url "
 
 (defvar *stop* nil)
 
-(defun request-loop (request-stream reply-stream)
-  (loop
-     (when *stop*
-       (return))
-     (handler-case
-         (let* ((req (make-instance 'request :stream request-stream))
-                (reply (make-instance 'reply :stream reply-stream))
-                (reader (request-reader req reply #'request-cont))
-                (result (funcall reader)))
-           (unless (eq :keep-alive result)
-             (return)))
-       (warning (w)
-         (format t "WARN ~A" w)
-         (force-output)
-         (continue)))))
-
 (defvar *acceptor-loop*)
 
 (defvar *host*)