[plt-scheme] Limiting Concurrent Connections to Web Server

From: Matthew Flatt (mflatt at cs.utah.edu)
Date: Fri Jan 16 11:03:21 EST 2009

At Fri, 16 Jan 2009 08:33:29 -0700, Jay McCarthy wrote:
>  (if (< i num)
>                    (wrap-evt in-ch
>                              (lambda (req)
>                                (channel-put (in-req-reply-ch req) #t)
>                                (loop (add1 i)
>                                      (list* (in-req-partner req) partners))))
>                    never-evt)

A detail that I didn't catch before: if the process that sends the
request terminates just before the `channel-put', then the lock server
can get get stuck trying to send a reply to a thread that isn't there

The simplest solution is to send the reply asynchronously:

 (wrap-evt in-ch
           (lambda (req)
             (thread (lambda ()
                       (channel-put (in-req-reply-ch req) #t)))
             (loop (add1 i)
                   (list* (in-req-partner req) partners))))

Another solution is to sync on a combination of the thread and a
channel-put evt:

 (lambda (req)
    (handle-evt (channel-put-evt (in-req-reply-ch req) #t)
       (lambda ()
         ;; notification accepted       
         (loop (add1 i)
               (list* (in-req-partner req) partners))))
     (handle-evt (in-req-partner req)
        (lambda ()
          ;; other thread died first
          (loop i partners)))))

Since your lock server already cleans up for partners that disappear,
though, the asynchronous reply is probably better.

If a thread can get suspended, and if you're using the latter solution,
then you'd want to go even further, and have the reply lifted up to the
main `sync' (because a suspended thread doesn't receive on a channel
but also isn't dead). I don't think that case applies in the web
server, though --- and the asynchronous reply covers that case, too.

Posted on the users mailing list.