posts: 09b
authorLucian Mogosanu <lucian@mogosanu.ro>
Fri, 16 Aug 2019 16:46:46 +0000 (19:46 +0300)
committerLucian Mogosanu <lucian@mogosanu.ro>
Fri, 16 Aug 2019 16:46:46 +0000 (19:46 +0300)
drafts/000-hunchentoot-v.markdown [deleted file]
posts/y06/09b-hunchentoot-v.markdown [new file with mode: 0644]

diff --git a/drafts/000-hunchentoot-v.markdown b/drafts/000-hunchentoot-v.markdown
deleted file mode 100644 (file)
index 9b84bcc..0000000
+++ /dev/null
@@ -1,258 +0,0 @@
----
-postid: 000
-title: Hunchentoot: taskmaster code review
-date: August 16, 2019
-author: Lucian MogoČ™anu
-tags: tech, tmsr
----
-
-Hunchentoot taskmasters are, as the name suggests, an abstraction for
-work management, or in other words, they implement decision-making for
-work distribution among processing units. On the surface they look
-very similar to Apache's [MPM][apache-mpm] model, which (again, viewed
-very superficially) suggests Hunchentoot was lispers' attempt at an
-Apache reimplementation.
-
-As presented in the earlier [architectural overview][ht-iii],
-taskmasters expose the following methods: execute-acceptor,
-handle-incoming-connection and shutdown. In very broad lines,
-execute-acceptor gets called on [start][ht-s] and sets up an execution
-context where [accept-connections][ht-ac] is called;
-handle-incoming-connection is then called on each new connection and
-calls [process-connection][ht-pc]; and finally, shutdown is called by
-[stop][ht-pc], to suspend processing on all threads. Additionally,
-(specific) taskmasters may expose other methods[^1] that specific to
-their operation.
-
-The taskmaster class provides three subclasses: a single-threaded
-implementation, an abstract "multi-threaded" taskmaster and a concrete
-"one thread per connection" taskmaster -- otherwise the coad under
-examination is also structured to accommodate the usual
-[ifdefisms][ht-ifdefism], which we'll blissfully ignore. This being
-said, let us look at each taskmaster and the method it implements.
-
-<a name="s3" href="#s3">[s3]</a> [**shutdown**][ht-s3]: This is a
-generic implementation, that can be (and is, in one case, as shown
-below) overriden by subclasses; this implementation doesn't do
-anything except returning the taskmaster object.
-
-[**single-threaded-taskmaster**][ht-stt]: The simplest taskmaster
-implementation; probably not very useful for battlefield use, because
-of poor load handling, [blocking operations][tlogz-1926874] and so on.
-
-<a name="stt-ea" href="#stt-ea">[stt-ea]</a>
-[**execute-acceptor**][ht-stt-ea]: Calls [accept-connections][ht-ac].
-
-<a name="stt-hic" href="#stt-hic">[stt-hic]</a>
-[**handle-incoming-connection**][ht-stt-hic]: Calls
-[process-connection][ht-pc].
-
-Shutdown is provided by the [generic implementation](#s3) above.
-
-[**multi-threaded-taskmaster**][ht-mtt]: Defines a new
-[acceptor-process][ht-mtt-ap] field denoting a new thread whose sole
-work is accepting new connections. Thus, this acceptor only provides
-an implementation for:
-
-<a name="mtt-ea" href="#mtt-ea">[mtt-ea]</a>
-[**execute-acceptor**][ht-mtt-ea]: Starts a new "listener" thread
-which waits for new connections; essentially the same as [the
-single-threaded version](#ht-stt-ea), only accept-connections runs on
-a separate thread.
-
-All the other methods are implemented by
-sub-multi-threaded-taskmasters, i.e. by
-one-thread-per-connection-taskmaster[^2].
-
-[**one-thread-per-connection-taskmaster**][ht-otpct]: As the name
-suggests, each new connection will spawn a new thread when it is to be
-handled. Up to [max-thread-count][ht-otpct-mtc] connections are
-accepted, and then the remaining connections up to
-[max-accept-count][ht-otpct-mac] are [queued][ht-otpct-wq] waiting for
-a thread to be allocated for them. If both counts are exceeded (or if
-the former is exceeded and the latter is not set) then a HTTP 503 is
-sent to the client.
-
-Below I'll detail (top-down) the implementation of
-handle-incoming-connection, shutdown and (the additional)
-initialize-instance -- the execute-acceptor used is that of the
-[superclass](#mtt-ea).
-
-<a name="otpct-ii" href="#otpct-hic">[otpct-ii]</a>
-[**initialize-instance**][ht-otpct-ii]: This is an ":after" method
-which, given a new taskmaster instance, does some sanity checking,
-i.e. that: a. if max-accept-count is supplied, then so is
-max-thread-count, and b. that the former is higher than the
-latter. The idea here is that the number of Hunchentoot worker threads
-is either unlimited, or limited by max-thread-count -- in the former
-case, max-accept-count doesn't really make sense, because all new
-connections are accepted.
-
-<a name="otpct-hic" href="#otpct-hic">[otpct-hic]</a>
-[**handle-incoming-connection**][ht-otpct-hic]: Calls
-[create-request-handler-thread](#otpct-crht); in other words, it
-creates a new thread to handle requests associated with the current
-connection.
-
-<a name="otpct-s3" href="#otpct-s3">[otpct-s3]</a>
-[**shutdown**][ht-otpct-s3]: Joins (in the Unix sense of "thread
-join") the acceptor-process, i.e. the [listener](#mtt-ea) thread and
-returns the current taskmaster.
-
-As observed, these methods are implemented using the following
-"support" methods and functions:
-
-<a name="otpct-itac" href="#otpct-itac">[otpct-itac]</a>
-[**increment-taskmaster-accept-count**][ht-otpct-itac]: Atomically
-increments the accept-count at a given time.
-
-<a name="otpct-dtac" href="#otpct-dtac">[otpct-dtac]</a>
-[**decrement-taskmaster-accept-count**][ht-otpct-dtac]: Atomically
-decrements the accept-count at a given time.
-
-<a name="otpct-ittc" href="#otpct-ittc">[otpct-ittc]</a>
-[**increment-taskmaster-thread-count**][ht-otpct-ittc]: Atomically
-increments the thread-count at a given time.
-
-<a name="otpct-dttc" href="#otpct-dttc">[otpct-dttc]</a>
-[**decrement-taskmaster-thread-count**][ht-otpct-dttc]: Atomically
-decrements the thread-count at a given time; when thread-count falls
-under max-accept-count, notifies listener via
-[note-free-connection](#otpct-nfc) that new connections may be
-handled.
-
-<a name="otpct-nfc" href="#otpct-nfc">[otpct-nfc]</a>
-[**note-free-connection**][ht-otpct-nfc]: [Signals][ht-cvs] the
-taskmaster's wait-queue; as the name suggests, it's used when there
-are "free" "slots" available for connections to be handled.
-
-<a name="otpct-wffc" href="#otpct-wffc">[otpct-wffc]</a>
-[**wait-for-free-connection**][ht-otpct-wffc]: [Waits][ht-cvw] for
-"free" connection "slots" on the taskmaster's wait-queue; used when
-there aren't (yet) enough resources to process a given connection.
-
-<a name="otpct-tmtr" href="#otpct-tmtr">[otpct-tmtr]</a>
-[**too-many-taskmaster-requests**][ht-otpct-tmtr]: Calls
-[acceptor-log-message][ht-alm]; logs the situation when the
-taskmaster's wait-queue is full or, if max-accept-count isn't set,
-that the thread-count has reached the ceiling i.e. max-thread-count.
-
-<a name="otpct-crht" href="#otpct-crht">[otpct-crht]</a>
-[**create-request-handler-thread**][ht-otpct-crht]: a. Wrapped in a
-[handler-case\*][ht-hcs]; b. start a new thread; c. which calls
-[handle-incoming-connection%](#otpct-hic2). In case of errors,
-d1. close the current connection's socket stream, aborting the
-connection; and d2. log the error.
-
-<a name="otpct-hic2" href="#otpct-hic2">[otpct-hic2]</a>
-[**handle-incoming-connection%**][ht-otpct-hic]: The description
-contained in the function's definition is pretty good, but
-nevertheless, let's look at this in more detail:
-a. [increment-taskmaster-accept-count](#otpct-itac); b. create a local
-binding for process-connection%, which b1. calls
-[process-connection][ht-pc] b2. with the [thread-count
-incremented](#otpct-ittc); c. implement the logic described below.
-
-c1. if thread-count is null, then [process-connection][ht-pc];
-otherwise, c2. *if* either max-accept-count is set and accept-count is
-at this threshold, *or* max-accept-count isn't set and thread-count is
-at the max-thread-count threshold, *then* call
-[too-many-taskmaster-requests](#otpct-tmtr) and
-[send-service-unavailable-reply](#otpct-ssur), which ends the current
-connection; otherwise, c3. *if* max-accept-count is set *and*
-thread-count is larger than max-thread-count *then*
-[wait-for-free-connection](#otpct-wffc), then, when unblocked,
-process-connection%; otherwise, c4. process-connection%.
-
-As can be observed, handle-incoming-connection% implements the bulk of
-the decision-making process for one-thread-per-connection
-taskmasters. This isn't *very* difficult to wrap one's head around,
-despite the apparent gnarl; simplifications, at the very least of an
-aesthetic nature, are possible, I'll leave them as a potential
-exploration exercise for a later date -- or, if the reader desires to
-chime in...
-
-<a name="otpct-ssur" href="#otpct-ssur">[otpct-ssur]</a>
-[**send-service-unavailable-reply**][ht-otpct-ssur]: Yet another pile
-of gnarl. Wraps everything in an [unwind-protect][clhs-up] and catches
-all potential conditions. In this context, it sends a
-http-service-unavailable message with the content set to the text
-returned by [acceptor-status-message][ht-asm].
-
-At the end, [decrement-taskmaster-accept-count](#otpct-dtac) and flush
-and close the connection stream.
-
-<a name="otpct-cas" href="#otpct-cas">[otpct-cas]</a>
-[**client-as-string**][ht-otpct-cas]: Convenience function used by
-[create-request-handler-thread](#otpct-crht) to give a name to the
-thread to be created, of the form "address:port".
-
-As can be seen, this is still a monster, albeit more organized than
-its [acceptor][ht-iv] brother. At this point, the big remaining pieces
-are requests, replies and handler dispatchers, which should provide us
-with almost[^3] everything we need to actually have a Hunchentoot.
-
-[^1]: Though all methods are piled together in the same place and,
-    say, default "thread count" implementations are provided for some
-    taskmasters that have nothing to do with multithreading. This is
-    a first sign that whoever wrote the code must have been fucked
-    in the head.
-
-[^2]: Which isn't to say there couldn't be more than one
-    multi-threaded-taskmaster implementation, we just haven't seen any
-    others. The very same, however, could be said about
-    e.g. shit. Sure, it could come from a human, a cow or a horse, but
-    for all intents and purposes it's still shit, so why the
-    additional layer of indirection?
-
-    Oh, it could be extended? Well, show me one of these
-    extensions. And if there are any, why aren't they in Hunchentoot?
-
-[^3]: There's tons of [glue][tmsr-work-iv] poured around this set of
-    fundamentally TCPistic web-server-pieces. Some of this glue I've
-    already reviewed proceeding for the components that use it; some
-    of it I haven't, and sooner or later I will, if only to establish
-    what's to stay and what's to go once I start cleaning the whole
-    thing up.
-
-[apache-mpm]: https://httpd.apache.org/docs/2.2/en/mpm.html
-[ht-iii]: /posts/y06/097-hunchentoot-iii.html
-[ht-iv]: /posts/y06/098-hunchentoot-iv.html
-[ht-stt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L127
-[ht-stt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L137
-[ht-stt-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L141
-[ht-mtt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L149
-[ht-mtt-ap]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L150
-[ht-mtt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L158
-[ht-otpct]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L175
-[ht-otpct-mtc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L177
-[ht-otpct-mac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L198
-[ht-otpct-wq]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L222
-[ht-otpct-ii]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L272
-[ht-otpct-itac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L281
-[ht-otpct-dtac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L286
-[ht-otpct-ittc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L291
-[ht-otpct-dttc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L296
-[ht-otpct-nfc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L306
-[ht-otpct-wffc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L311
-[ht-otpct-tmtr]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L317
-[ht-otpct-crht]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L322
-[ht-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L345
-[ht-otpct-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L348
-[ht-otpct-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L354
-[ht-otpct-hic2]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L359
-[ht-otpct-ssur]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L392
-[ht-otpct-cas]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L416
-[ht-cvs]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L132
-[ht-cvw]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L135
-[ht-hcs]: http://coad.thetarpit.org/hunchentoot/c-conditions.lisp.html#L121
-[ht-s]: /posts/y06/098-hunchentoot-iv.html#s
-[ht-s2]: /posts/y06/098-hunchentoot-iv.html#s2
-[ht-ac]: /posts/y06/098-hunchentoot-iv.html#ac
-[ht-pc]: /posts/y06/098-hunchentoot-iv.html#pc
-[ht-alm]: /posts/y06/098-hunchentoot-iv.html#alm
-[ht-asm]: /posts/y06/098-hunchentoot-iv.html#asm
-[ht-ifdefism]: /posts/y06/098-hunchentoot-iv.html#selection-195.296-199.206
-[tlogz-1926874]: http://logs.nosuchlabs.com/log/trilema/2019-08-09#1926874
-[clhs-up]: http://clhs.lisp.se/Body/s_unwind.htm
-[tmsr-work-iv]: /posts/y06/099-tmsr-work-iv.html#selection-139.61-139.151
diff --git a/posts/y06/09b-hunchentoot-v.markdown b/posts/y06/09b-hunchentoot-v.markdown
new file mode 100644 (file)
index 0000000..47e5fc9
--- /dev/null
@@ -0,0 +1,298 @@
+---
+postid: 09b
+title: Hunchentoot: taskmaster code review
+date: August 16, 2019
+author: Lucian MogoČ™anu
+tags: tech, tmsr
+---
+
+This post is part of a series on [Common Lisp WWWism][cl-www], more
+specifically of [ongoing work][hunchentoot-ii] to [saw
+apart][hunchentoot-iii] Hunchentoot into pieces and [own][own] them
+and the whole of this Common Lisp web server. The second fundamental
+component of Hunchentoot, next to the so-called
+[acceptor][hunchentoot-iv], is the so-called taskmaster.
+
+Hunchentoot taskmasters are, as the name suggests, an abstraction for
+work management, or in other words, a mechanism implementing work
+distribution among processing units. On the surface they look very
+similar to Apache's [MPM][apache-mpm] model, which (again, viewed very
+superficially) suggests Hunchentoot was an attempt at a Lisp-style
+(re)implementation of Apache. This, as a side note, doesn't really
+speak in its favour. We do know, however, what the current coad [is
+made of][tlogz-1926027], and it's yet to be seen whether it can even
+be retrofitted into something that fits in head, as it's otherwise by
+all looks as usable as a [CL-on-Unix][alf-cl-on-pc]-on-top-of-TCP
+application can be. It's not like there's a better [CL
+item][mp-comment] to work with anyway, so that's that.
+
+As presented in the earlier [architectural overview][hunchentoot-iii],
+taskmasters expose the following methods: execute-acceptor,
+handle-incoming-connection and shutdown. In very broad lines,
+execute-acceptor gets called on [start][ht-s] and sets up an execution
+context where [accept-connections][ht-ac] is called;
+handle-incoming-connection is then called on each new connection,
+where it calls [process-connection][ht-pc]; and finally, shutdown is
+called by [stop][ht-pc], in order to suspend request processing on all
+threads. Additionally, (more specific) taskmasters may expose other
+methods[^1] specific to their operation.
+
+The taskmaster class provides three subclasses: a single-threaded
+implementation, an abstract "multi-threaded" taskmaster and a concrete
+"one thread per connection" taskmaster descending from the
+multi-threaded one -- otherwise the coad under examination is also
+structured to accommodate the usual [ifdefisms][ht-ifdefism], which
+we'll blissfully ignore. This being said, let us look at each
+taskmaster and the method it implements. First, we notice that
+shutdown is given an implementation for all taskmasters:
+
+<a name="s3" href="#s3">[s3]</a> [**shutdown**][ht-s3]: This is a
+generic implementation, that can be (and is, in one case, as shown
+below) overriden by subclasses; this implementation doesn't do
+anything except returning the taskmaster object.
+
+**[[]]** [**single-threaded-taskmaster**][ht-stt]: The simplest
+taskmaster implementation; probably not very useful for battlefield
+use, because of poor load handling, [blocking
+operations][tlogz-1926874] and so on.
+
+<a name="stt-ea" href="#stt-ea">[stt-ea]</a>
+[**execute-acceptor**][ht-stt-ea]: Calls [accept-connections][ht-ac].
+
+<a name="stt-hic" href="#stt-hic">[stt-hic]</a>
+[**handle-incoming-connection**][ht-stt-hic]: Calls
+[process-connection][ht-pc].
+
+Shutdown is provided by the [generic implementation](#s3) above.
+
+**[[]]** [**multi-threaded-taskmaster**][ht-mtt]: Defines a new
+[acceptor-process][ht-mtt-ap] field denoting a new thread whose sole
+work is accepting new connections. Thus, this acceptor only provides
+an implementation for:
+
+<a name="mtt-ea" href="#mtt-ea">[mtt-ea]</a>
+[**execute-acceptor**][ht-mtt-ea]: Starts a new "listener" thread
+which waits for new connections; essentially the same as [the
+single-threaded version](#ht-stt-ea), only now accept-connections runs
+on a separate thread.
+
+All the other methods are implemented by
+sub-multi-threaded-taskmasters, i.e. by
+one-thread-per-connection-taskmaster[^2].
+
+**[[]]** [**one-thread-per-connection-taskmaster**][ht-otpct]: As the name
+suggests, each new connection will spawn a new thread when it is to be
+handled. Up to [max-thread-count][ht-otpct-mtc] connections are
+accepted, and then the remaining connections up to
+[max-accept-count][ht-otpct-mac] are [queued][ht-otpct-wq] waiting for
+a thread to be allocated for them. If both counts are exceeded (or if
+the former is exceeded and the latter is not set) then a HTTP 503 is
+sent to the client.
+
+Below I'll detail (top-down) the implementation of
+handle-incoming-connection, shutdown and (the additional)
+initialize-instance -- the execute-acceptor in use is that of the
+[father-class](#mtt-ea).
+
+<a name="otpct-ii" href="#otpct-hic">[otpct-ii]</a>
+[**initialize-instance**][ht-otpct-ii]: This is an ":after" method
+which, given a new taskmaster instance, does some sanity checking,
+i.e. that: a. if max-accept-count is supplied, then so is
+max-thread-count, and b. that the former is higher than the
+latter. The idea here is that the number of Hunchentoot worker threads
+is either unlimited[^3], or limited by max-thread-count -- in the
+former case, max-accept-count doesn't really make sense, because new
+connections never get blocked in the wait-queue.
+
+<a name="otpct-hic" href="#otpct-hic">[otpct-hic]</a>
+[**handle-incoming-connection**][ht-otpct-hic]: Calls
+[create-request-handler-thread](#otpct-crht); in other words, it
+creates a new thread to handle requests associated with the current
+connection.
+
+<a name="otpct-s3" href="#otpct-s3">[otpct-s3]</a>
+[**shutdown**][ht-otpct-s3]: Joins (in the Unix sense of "thread
+join") the acceptor-process, i.e. the [listener](#mtt-ea) thread and
+returns the current taskmaster.
+
+As observed, these methods are implemented using the following
+"support" methods and functions:
+
+<a name="otpct-itac" href="#otpct-itac">[otpct-itac]</a>
+[**increment-taskmaster-accept-count**][ht-otpct-itac]: Atomically
+increments the accept-count at a given time.
+
+<a name="otpct-dtac" href="#otpct-dtac">[otpct-dtac]</a>
+[**decrement-taskmaster-accept-count**][ht-otpct-dtac]: Atomically
+decrements the accept-count at a given time.
+
+<a name="otpct-ittc" href="#otpct-ittc">[otpct-ittc]</a>
+[**increment-taskmaster-thread-count**][ht-otpct-ittc]: Atomically
+increments the thread-count at a given time.
+
+<a name="otpct-dttc" href="#otpct-dttc">[otpct-dttc]</a>
+[**decrement-taskmaster-thread-count**][ht-otpct-dttc]: Atomically
+decrements the thread-count at a given time; when thread-count falls
+under max-accept-count, notifies listener via
+[note-free-connection](#otpct-nfc) that new connections may be
+handled.
+
+<a name="otpct-nfc" href="#otpct-nfc">[otpct-nfc]</a>
+[**note-free-connection**][ht-otpct-nfc]: [Signals][ht-cvs] the
+taskmaster's wait-queue; as the name suggests, it's used when there
+are "free" "slots" available for connections to be handled.
+
+<a name="otpct-wffc" href="#otpct-wffc">[otpct-wffc]</a>
+[**wait-for-free-connection**][ht-otpct-wffc]: [Waits][ht-cvw] for
+"free" connection "slots" on the taskmaster's wait-queue; used in
+[handle-incoming-connection%](#otpct-hic2) when there aren't (yet)
+enough resources to process a given connection.
+
+<a name="otpct-tmtr" href="#otpct-tmtr">[otpct-tmtr]</a>
+[**too-many-taskmaster-requests**][ht-otpct-tmtr]: Calls
+[acceptor-log-message][ht-alm]; logs the situation when the
+taskmaster's wait-queue is full or, if max-accept-count isn't set,
+that the thread-count has reached the ceiling i.e. max-thread-count.
+
+<a name="otpct-crht" href="#otpct-crht">[otpct-crht]</a>
+[**create-request-handler-thread**][ht-otpct-crht]: a. Wrapped in a
+[handler-case\*][ht-hcs]; b. start a new thread; c. which calls
+[handle-incoming-connection%](#otpct-hic2). In case of errors,
+d1. close the current connection's socket stream, aborting the
+connection; and d2. [log][ht-lms] the error.
+
+<a name="otpct-hic2" href="#otpct-hic2">[otpct-hic2]</a>
+[**handle-incoming-connection%**][ht-otpct-hic]: The description
+contained in the function's definition is pretty good, but
+nevertheless, let's look at this in more detail:
+a. [increment-taskmaster-accept-count](#otpct-itac); b. create a local
+binding for process-connection%, which b1. calls
+[process-connection][ht-pc] b2. with the [thread-count
+incremented](#otpct-ittc); c. implement the logic described below.
+
+c1. if thread-count is null, then [process-connection][ht-pc];
+otherwise, c2. *if* either max-accept-count is set and accept-count is
+at this threshold, *or* max-accept-count isn't set and thread-count is
+at the max-thread-count threshold, *then* call
+[too-many-taskmaster-requests](#otpct-tmtr) and
+[send-service-unavailable-reply](#otpct-ssur), which ends the current
+connection; otherwise, c3. *if* max-accept-count is set *and*
+thread-count is larger than max-thread-count *then*
+[wait-for-free-connection](#otpct-wffc), then, when unblocked,
+process-connection%; otherwise, c4. process-connection%.
+
+As can be observed, handle-incoming-connection% implements the bulk of
+the decision-making process for one-thread-per-connection
+taskmasters. This isn't *very* difficult to wrap one's head around,
+despite the apparent gnarl; simplifications, at the very least of an
+aesthetic nature, are possible, I'll leave them as a potential
+exploration exercise for a later date -- or, if the reader desires to
+chime in...
+
+<a name="otpct-ssur" href="#otpct-ssur">[otpct-ssur]</a>
+[**send-service-unavailable-reply**][ht-otpct-ssur]: Yet another pile
+of gnarl. Wraps everything in an [unwind-protect][clhs-up] and catches
+all potential conditions. In this context, it sends a
+http-service-unavailable message with the content set to the text
+returned by [acceptor-status-message][ht-asm].
+
+At the end, [decrement-taskmaster-accept-count](#otpct-dtac) and flush
+and close the connection stream.
+
+<a name="otpct-cas" href="#otpct-cas">[otpct-cas]</a>
+[**client-as-string**][ht-otpct-cas]: Convenience function used by
+[create-request-handler-thread](#otpct-crht) to give a name to the
+thread to be created, of the form "address:port".
+
+To conclude: as can be seen, this is still a monster, albeit more
+organized than its [acceptor][hunchentoot-iv] brother. At this point,
+the big remaining pieces are requests, replies and handler
+dispatchers, which should provide us with almost[^4] everything we
+need to actually have a Hunchentoot.
+
+Meta: blog comments are for now still missing; thus readers are
+invited to leave them in [#spyked][contact] or (assuming they know
+where they're heading)
+#trilema. Existing comments are preserved here in [^5].
+
+[^1]: Though all methods are piled together in the same place and,
+    say, default "thread count" implementations are provided for some
+    taskmasters that have nothing to do with multithreading. This is
+    IMHO a very early sign that whoever wrote the code must have been
+    fucked in the head.
+
+[^2]: Which isn't to say there couldn't be more than one
+    multi-threaded-taskmaster implementation, we just haven't seen any
+    others. The very same, however, could be said about e.g. shit:
+    sure, it could come from a human, a cow or a horse, but for all
+    intents and purposes it's still shit, so why the additional layer
+    of indirection?
+
+    Oh, it could be extended? Well, show me one of these
+    extensions. And if there are any, why aren't they in Hunchentoot?
+
+[^3]: Which is in principle a very stupid idea, since computing
+    practice shows that resources are always limited, no matter how
+    many extra compute nodes or how much disk space, bandwidth
+    etc. you're willing to get. Then again, who's to say that the
+    webserver implementation oughta tell the operator how he should
+    run his program?
+
+[^4]: There's tons of [glue][tmsr-work-iv] poured around this set of
+    fundamentally TCPistic web-server-pieces. Some of this glue I've
+    already reviewed proceeding for the components that use it; some
+    of it I haven't, and sooner or later I will, if only to establish
+    what's to stay and what's to go once I start cleaning the whole
+    thing up.
+
+[^5]: No comments thus far.
+
+[ht-stt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L127
+[ht-stt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L137
+[ht-stt-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L141
+[ht-mtt]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L149
+[ht-mtt-ap]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L150
+[ht-mtt-ea]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L158
+[ht-otpct]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L175
+[ht-otpct-mtc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L177
+[ht-otpct-mac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L198
+[ht-otpct-wq]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L222
+[ht-otpct-ii]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L272
+[ht-otpct-itac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L281
+[ht-otpct-dtac]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L286
+[ht-otpct-ittc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L291
+[ht-otpct-dttc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L296
+[ht-otpct-nfc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L306
+[ht-otpct-wffc]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L311
+[ht-otpct-tmtr]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L317
+[ht-otpct-crht]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L322
+[ht-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L345
+[ht-otpct-s3]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L348
+[ht-otpct-hic]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L354
+[ht-otpct-hic2]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L359
+[ht-otpct-ssur]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L392
+[ht-otpct-cas]: http://coad.thetarpit.org/hunchentoot/c-taskmaster.lisp.html#L416
+[ht-cvs]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L132
+[ht-cvw]: http://coad.thetarpit.org/hunchentoot/c-compat.lisp.html#L135
+[ht-hcs]: http://coad.thetarpit.org/hunchentoot/c-conditions.lisp.html#L121
+[ht-s]: /posts/y06/098-hunchentoot-iv.html#s
+[ht-s2]: /posts/y06/098-hunchentoot-iv.html#s2
+[ht-ac]: /posts/y06/098-hunchentoot-iv.html#ac
+[ht-pc]: /posts/y06/098-hunchentoot-iv.html#pc
+[ht-alm]: /posts/y06/098-hunchentoot-iv.html#alm
+[ht-asm]: /posts/y06/098-hunchentoot-iv.html#asm
+[ht-lms]: /posts/y06/098-hunchentoot-iv.html#lms
+[ht-ifdefism]: /posts/y06/098-hunchentoot-iv.html#selection-195.296-199.206
+[cl-www]: /posts/y05/090-tmsr-work-ii.html#selection-108.0-108.17
+[hunchentoot-ii]: /posts/y05/096-hunchentoot-ii.html
+[hunchentoot-iii]: /posts/y06/097-hunchentoot-iii.html
+[hunchentoot-iv]: /posts/y06/098-hunchentoot-iv.html
+[own]: /posts/y04/069-on-intellectual-ownership.html
+[apache-mpm]: https://httpd.apache.org/docs/2.2/en/mpm.html
+[tlogz-1926027]: http://logs.nosuchlabs.com/log/trilema/2019-08-01#1926027
+[alf-cl-on-pc]: http://trilema.com/2019/trilema-goes-dark/#comment-130686
+[mp-comment]: /posts/y06/098-hunchentoot-iv.html#comment3
+[tlogz-1926874]: http://logs.nosuchlabs.com/log/trilema/2019-08-09#1926874
+[clhs-up]: http://clhs.lisp.se/Body/s_unwind.htm
+[tmsr-work-iv]: /posts/y06/099-tmsr-work-iv.html#selection-139.61-139.151
+[contact]: http://webchat.freenode.net/?channels=#spyked&nick=f_thetarpit_09b