chicken-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Chicken-users] srfi-18 and reading/writing variables, how to simulate a


From: Matt Welland
Subject: [Chicken-users] srfi-18 and reading/writing variables, how to simulate a collision?
Date: Tue, 29 Nov 2016 23:30:02 -0700

My question: Do green threads naturally do atomic reads/writes to variables such that mutexes are pragmatically not needed in most situations in Chicken?

I have seen corrupted values which I assumed were due to reading/writing to variables from multiple threads without mutex protection. However when I tried to simulate this (code pasted below) I haven't been able to create any collisions.

Note that where file handles and ports are being opened/closed with subprocesses etc then mutexes are absolutely needed. I ran into this with trying to use nanomsg in threads where subprocesses were being launched. Without mutexes it crashed very quickly. It is possible that the corrupted values I've seen in the past were actually due to open/closing of file handles, ports and or processes along with cross threaded variable accesses.

But back to the question, are mutexes really needed when passing variables back and forth between srfi-18 threads in Chicken? Perhaps my code below is too simplistic to trigger a collision? Mutexes can have a pretty severe impact on performance and it would be nice to know when they are really needed. The srfi-18 documentation is crystal clear that they should be used always but maybe in the case of chicken it is ok to bend the rules?

Thanks.
=====================
(use posix srfi-18 typed-records srfi-69)

(define-inline (with-mutex mtx accessor record . val)
  (mutex-lock! mtx)
  (let ((res (apply accessor record val)))
    (mutex-unlock! mtx)
    res))

(defstruct testit
  (x 0)
  (y 0))

(define *validvals* '(0 1 2 a b c d e f 3 4 5 6 7 8 9 "x" "y" "z" "*" "-"))
(define *numvals*   (length *validvals*))
(define *mtx* (make-mutex))

;; uncomment to try with a struct along with a mutex
(define *struct* (make-testit))
(define-inline (get-val)(with-mutex *mtx* testit-x *struct*))
(define-inline (set-val v)(with-mutex *mtx* testit-x-set! *struct* v))

;; uncomment to try with a struct, no mutex
;; (define *struct* (make-testit))
;; (define-inline (get-val)(testit-x *struct*))
;; (define-inline (set-val v)(testit-x-set! *struct* v))

;; uncomment to try with a global var, no mutex
;; (define *var* 0)
;; (define-inline (get-val) *var*)
;; (define-inline (set-val v) (set! *var* v))

;; uncomment to try with a hash table and no mutex
;; (define *var* (make-hash-table))(hash-table-set! *var* "value" 0)
;; (define-inline (get-val)(hash-table-ref *var* "value"))
;; (define-inline (set-val v)(hash-table-set! *var* "value" v))

(define (mod-struct)
  (let loop ((c 10000)
             (last-val #t)
             (same-count 0))
     (if (> c 0)
         (begin
            (if (not (member (get-val) *validvals*))
                (print "BAD VALUE: " (get-val)))
            (set-val (list-ref *validvals* (random *numvals*)))
            ;; (display (with-mutex *mtx* testit-x *struct*))
            (loop (- c 1) (get-val) (+ same-count (if (eq? (get-val) last-val) 1 0))))
         (print "All done, same-count=" same-count " c=" c))))

(let ((threads (let loop ((c 100)
                          (r '()))
                  (if (> c 0)
                      (loop (- c 1)
                            (cons (make-thread mod-struct (conc "mod-struct-" c)) r))
                      r))))
   (map thread-start! threads)
   (map thread-join!  threads))


reply via email to

[Prev in Thread] Current Thread [Next in Thread]