Mark Evenson evenson@panix.com writes:
On Sep 27, 2013, at 9:28 PM, Mark Evenson evenson@panix.com wrote:
On Sep 27, 2013, at 8:13 PM, "Alan Ruttenberg" alanruttenberg@gmail.com wrote:
Agreed. While the gethash and puthash should independently work, the combination of the two isn't thread safe. For example two processes could get the value in the ht before either has a chance to write back the increment.
A version that only adds to unique keys in the hash table, relying on the HASH-TABLE-COUNT value to indicate successful update. The keys are the squares of the first eight primes, so the total threads spawned is eight. the parameter to RUN now indicates how many squares of the given prime basis. But still weirdness, in that the first thread which should increment the keys of the hashtable indexed by the powers of 2 doesn't seem to execute. Something in my LOOP clause?
<threaded-hash.lisp>
Indeed a faulty understanding of LOOP:
CL-USER> (loop :for n :in '(2 3 5 7 11 13 15 17) :doing (threads:make-thread (lambda () (format t "~A " n))))
3 5 7 11 13 15 17 17 NIL
The value of "n" has already been incremented past the first member of the list when the closure is created with LAMBDA, so the thread with "2" never gets executed.
SLIME users: one needs to place the form (setf swank:*globally-redirect-io* t) in ~/.swank.lisp to get all the FORMAT output in the REPL buffer. Otherwise look in the corresponding *inferior-lisp* buffer.
So, I guess one should loop over closures that have been correctly initialized with the right values in some other manner. I'd go for using DO over LOOP for unless someone can correct my understanding. Either that, or I need to follow macro expansions.
DO won't help better. For LOOP, DOTIMES, DOLIST, it's unspecified whether the variables are new bindings or updated bindings. But for DO and DO*, it is specified they're updated. So while with the former you had a chance for it to work (not conformingly), you stand no such chance with DO.
What you must write is:
(ql:quickload :bordeaux-threads)
(loop :for n :in '(2 3 5 7 11 13 15 17) :do (let ((n n)) (bt:make-thread (lambda () (format t "~A " n)))))
(do ((ns '(2 3 5 7 11 13 15 17) (cdr ns))) ((null ns)) (let ((n (car ns))) (bt:make-thread (lambda () (format t "~A " n)))))