[plt-scheme] Creating a suspended thread

From: Marc Feeley (feeley at iro.umontreal.ca)
Date: Mon Apr 13 16:39:32 EDT 2009

On 13-Apr-09, at 10:24 AM, Matthew Flatt wrote:

> At Mon, 13 Apr 2009 16:36:45 +0300, R. Emre Başar wrote:
>> I'm tryring to create a thread which is initially suspended.  As  
>> far as
>> I know, (thread (lambda () ...)) creates a thread and runs it  
>> instantly.
>> Is it possible to create a thread in suspended state to resume later?
>>
>> I know it's possible to create and suspend it afterwards but our
>> application is rather time intensive so I don't want it to have  
>> even a
>> little chance to run.
>
> Matthias asks a good question, but...
>
> (define (thread/suspended thunk)
>   (let* ([s (make-semaphore)]
>          [t (thread (lambda ()
>                       (semaphore-wait s)
>                       (thunk)))])
>     (thread-suspend t)
>     (semaphore-post s)
>     t))
>
> In practice, `thread-suspend' will suspend the new thread before it is
> ever swapped in. In the unlikely event that the creating thread is
> swapped out before it can suspend the new one, the semaphore prevents
> the new thread from making any progress. (The semaphore operations are
> all cheap.)

Does PLT support SRFI 18?  The SRFI 18 API for thread creation  
distinguishes thread creation (make-thread) and thread activation  
(thread-start!).  The usefulness of this is explained in the SRFI 18  
spec under "thread-start!":

NOTE: It is useful to separate thread creation and thread activation  
to avoid the race condition that would occur if the created thread  
tries to examine a table in which the current thread stores the  
created thread. See the last example of thread-terminate! which  
contains mutually recursive threads.

and the example from "thread-terminate!" is

     (define (amb thunk1 thunk2)
       (let ((result #f)
             (result-mutex (make-mutex))
             (done-mutex (make-mutex)))
         (letrec ((child1
                   (make-thread
                     (lambda ()
                       (let ((x (thunk1)))
                         (mutex-lock! result-mutex #f #f)
                         (set! result x)
                         (thread-terminate! child2)
                         (mutex-unlock! done-mutex)))))
                  (child2
                   (make-thread
                     (lambda ()
                       (let ((x (thunk2)))
                         (mutex-lock! result-mutex #f #f)
                         (set! result x)
                         (thread-terminate! child1)
                         (mutex-unlock! done-mutex))))))
           (mutex-lock! done-mutex #f #f)
           (thread-start! child1)
           (thread-start! child2)
           (mutex-lock! done-mutex #f #f)
           result)))

Delayed activation is essential for creating mutually recursive threads.

Marc



Posted on the users mailing list.