[plt-scheme] Thread synchronization for dummies

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

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.