[plt-scheme] thread-suspend/thread-resume versus semaphores

From: Jens Axel Søgaard (jensaxel at soegaard.net)
Date: Mon Aug 22 18:33:48 EDT 2005

Hi all,

I am currently working on interfacing MzScheme with MLton. The
initial experiments has turned out well and now I am trying to
make Scheme side as "schemy" as possible. This entail making
MLton returned values look and behave as normal Scheme values.
In particular I want automatic deallocation of values returned
from the ML side, when the corresponding Scheme object becomes

In order to do this I register all values on the Scheme side
with a will-executor.

(define ml-will-executor (make-will-executor))
(define (ml-will-register-root r)
   (will-register ml-will-executor r
                  (lambda (r) ((root-unreg r) (root-id r)))))

Here the result of (root-unreg r) is a function imported from MLton
and knows how to unregister roots of the type r has.

Since functions registered with the will-executor needs to be run,
one is adviced in the manual to use a separate thread for this:

(define will-thread (thread (lambda ()
                               (let loop ()
                                 (will-execute ml-will-executor)

This sort of works, but there is a caveat. The MLton function
that unregisters a root may provoke a garbage collection. Since
the MLton garbage collector is a moving collector, I therefore
need to ensure that the wills aren't run in code sections where 
C-pointers to the ML values are used (e.g. when elements in an array
is referenced). In other words I need a to implement
(critical-region body ...) which stops the will-executor
during the evaluation of the bodies.

The direct approach is to use thread-suspend/thread-resume:

(define-syntax critical-region
   (syntax-rules ()
     ((critical-region body ...)
      (let ()
        (thread-suspend will-thread)
          (begin body ...)
          (thread-resume will-thread))))))

An alternative would be to introduce a semaphore, and let
the critical regions raise/lower the semaphore and only allow
the will-executor to run when the semaphore is down.

My question is now, whether the thread-suspend/thread-resume approach
is just as efficient as a semaphore solution would be?

Or perhaps a third approach is better?

Jens Axel Søgaard

Posted on the users mailing list.