[plt-scheme] Creating a suspended thread
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