[hunchentoot-devel] spawning threads
Faré
fahree at gmail.com
Thu Mar 21 19:03:41 UTC 2013
On Thu, Mar 21, 2013 at 12:14 AM, Faré <fahree at gmail.com> wrote:
> In quux-hunchentoot, I introduce a gf
>
> (defgeneric start-thread (context thunk &key))
>
> with a method
>
> (defmethod start-thread ((taskmaster thread-pooling-taskmaster) thunk &key name)
> (declare (ignorable taskmaster))
> (bt:make-thread thunk :name name))
>
> that offers an extension point so that applications can specify
> bindings, handlers, etc.,
> around the spawning of threads.
>
> I believe this technique could be advantageously adopted by
> hunchentoot in general.
>
> PS: if this reminds you of "interface-passing style", that's not a coincidence.
>
Here's the code I'd like to see used (with the function exported):
(in-package :quux-hunchentoot)
(defgeneric start-thread (context thunk &key))
(defmethod start-thread (context thunk &key name)
(declare (ignorable context))
#-lispworks
(bt:make-thread thunk :name name)
#+lispworks
(mp:process-run-function name nil thunk))
;;; This overrides the default methods from hunchentoot/taskmaster.lisp,
;;; providing the desired extension point, so you can wrap the
hunchentoot-provided thunk
;;; in a set of default bindings, condition handlers, etc.
(defmethod execute-acceptor ((taskmaster one-thread-per-connection-taskmaster))
(setf (acceptor-process taskmaster)
(start-thread
taskmaster
(lambda ()
(accept-connections (taskmaster-acceptor taskmaster)))
:name (format nil "hunchentoot-listener-~A:~A"
(or (acceptor-address (taskmaster-acceptor
taskmaster)) "*")
(acceptor-port (taskmaster-acceptor taskmaster))))))
(defmethod create-request-handler-thread ((taskmaster
one-thread-per-connection-taskmaster) socket)
"Create a thread for handling a single request"
;; we are handling all conditions here as we want to make sure that
;; the acceptor process never crashes while trying to create a
;; worker thread; one such problem exists in
;; GET-PEER-ADDRESS-AND-PORT which can signal socket conditions on
;; some platforms in certain situations.
(handler-case*
(start-thread
taskmaster
(lambda () (handle-incoming-connection% taskmaster socket))
:name (format nil (taskmaster-worker-thread-name-format
taskmaster) (client-as-string socket)))
(error (cond)
;; need to bind *ACCEPTOR* so that LOG-MESSAGE* can do its work.
(let ((*acceptor* (taskmaster-acceptor taskmaster)))
(ignore-errors
(close (make-socket-stream socket *acceptor*) :abort t))
(log-message* *lisp-errors-log-level*
"Error while creating worker thread for new
incoming connection: ~A" cond)))))
—♯ƒ • François-René ÐVB Rideau •Reflection&Cybernethics• http://fare.tunes.org
I discovered a few years ago that happiness was something you put into life,
not something you get out of it — and I was transformed.
More information about the Tbnl-devel
mailing list