[plt-scheme] Thread synchronization for dummies

From: Carl Eastlund (carl.eastlund at gmail.com)
Date: Thu May 28 15:27:01 EDT 2009

It has been pointed out to me privately that my response isn't really
answering your question, which is not simply "can threads, channels,
and other synchronization primitives be strung together to make a
synchronized function", but rather "is there an automatic way to
declare a function as synchronous".  I don't believe there is (and
sorry for my misreading).  However, there is probably a simple (for
someone familiar with these primitives) way to write a
define/synchronized macro.  If I can come up with one that you can
simply copy/paste into your code (and that can later be added to a
reusable library) I'll let you know.

--Carl

On Thu, May 28, 2009 at 3:17 PM, Carl Eastlund <carl.eastlund at gmail.com> wrote:
> On Thu, May 28, 2009 at 3:04 PM, Erich Rast <erich at snafu.de> wrote:
>>> d reference material for PLT Scheme's concurrency operations here:
>>>
>>> http://docs.plt-scheme.org/reference/concurrency.
>>>
>> Yep, I've seen this.
>>
>>> What I would suggest for your operation is spawning a dedicated thread
>>> to handle FOO requests.  Whenever FOO gets called, it should send a
>>> message to that thread, then block to wait for a response.  That
>>> thread should wait for requests, and for each one should handle the
>>> request and send a response before waiting for the next request.  This
>>> will guarantee each request will be handled in order and will not
>>> overlap.
>>>
>>> Look at the documentation for creating threads (for your request
>>> thread) and on channels (for sending, waiting for, and receiving
>>> requests/responses).
>>
>> That sounds awfully complicated and I was hoping there was an easier
>> solution. Anyway, thanks for the advice and I'll dig some more into the
>> world of threads/semaphore/mutexes and whatever else there is.
>>
>> --Erich
>
> The actual code isn't that long.  Here's some example code.  It starts
> a server thread that accepts action requests: arbitrary functions that
> should be run one at a time, and whose return value should be sent
> back.  It then runs two clients, A and B, which request start and end
> messages with a pause in between.  The requests will never interleave:
> you'll never see a B message in between A start and end messages, and
> vice versa.
>
> All you should have to change for your FOO function is the server
> function and the client function -- instead of the client sending a
> thunk, and the server accepting and running a thunk, replace them with
> whatever data structure and action you actually need to process.
>
> #lang scheme
>
> ;; SERVER SETUP
>
> (define (server)
>  (let* ([action (channel-get request-channel)]
>         [result (action)])
>    (channel-put response-channel result)
>    (server)))
>
> (define request-channel (make-channel))
> (define response-channel (make-channel))
> (define server-thread (thread server))
>
> ;; REQUEST FUNCTION
> (define (request action)
>  (channel-put request-channel action)
>  (channel-get response-channel))
>
> ;; CLIENT SETUP
>
> (define (client name)
>  (lambda ()
>    (let loop ()
>      (sleep (random))
>      (request (lambda ()
>                 (printf "~a: START\n" name)
>                 (sleep (random))
>                 (printf "~a: END\n" name)))
>      (loop))))
>
> ;; TWO SIMULTANEOUS CLIENTS
> (thread (client "A"))
> (thread (client "B"))
>
> --
> Carl Eastlund


Posted on the users mailing list.