[plt-scheme] set! with structs

From: Carl Eastlund (cce at ccs.neu.edu)
Date: Mon Nov 12 22:16:31 EST 2007

The set! form is not the atomic unit of mutation, it's the tool for
mutating lexically bound variables.  A structure field isn't one of
those, so structure mutators don't use set!.  Since you've rebound
set! but not structure mutators, I don't know how your tool is
detecting any mutation in the code below.  If it's only complaining
about the reference to "a", regardless of mutation, then the mutators
aren't your problem to begin with.  In any event, if you want to take
control of structure mutators, you'll have to bind your own


On Nov 12, 2007 8:45 PM, Jon Rafkind <workmin at ccs.neu.edu> wrote:
> Hi,
>     I wrote a small module language for detecting race conditions by exporting my own versions of %#app and set!, among other things. The language works fine for normal variables but I was surprised to see races reported for different fields of structs. Like
> (define-struct foo (x y))
> (define a (make-foo 1 2))
> (thread (lambda () (set-foo-x! a 1)))
> (thread (lambda () (set-foo-y! a 1)))
> Should be ok since different variables are being touched but the tool still complains because 'a' is used in two different threads without any locking. Long story short: how does 'set-foo-x!' eventually convert into 'set!' ? Is it actually dangerous to mutate fields of a structure in separate threads, in which case the tool told me something interesting?
> Basically my tool keeps track of which threads accessed a given variable by testing the type during #%app and set!, but after looking at the transformation of set-foo-x! in the macro stepper I don't see where set! is being involved at all. It looks like set-foo-x! is bound to a (make-struct-mutator) thing which is a primitive defined in src/struct.c
> FWIW, this is my set! macro
>   (define-syntax (shared-set! stx)
>     (syntax-case stx ()
>       ((_ id expr)
>        (if (not (identifier? #'id))
>          (raise-syntax-error #f "not an identifier" stx #'id)
>          #'(cond
>            ((shared? id)
>             (begin
>               (do-access id) ;; this will report a race if one exists
>               (set-shared-expr! id expr)))
>            (else (set! id expr)))))))

Posted on the users mailing list.