[plt-scheme] set! with structs

From: Jon Rafkind (workmin at ccs.neu.edu)
Date: Mon Nov 12 20:45:16 EST 2007

    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)
           ((shared? id)
              (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.