[armedbear-devel] Pure threads and hashtables test

Pascal J. Bourguignon pjb at informatimago.com
Sat Sep 28 15:39:56 UTC 2013


Mark Evenson <evenson at panix.com> writes:

> On Sep 27, 2013, at 9:28 PM, Mark Evenson <evenson at panix.com> wrote:
>
>> 
>> On Sep 27, 2013, at 8:13 PM, "Alan Ruttenberg" <alanruttenberg at 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)))))

-- 
__Pascal Bourguignon__
http://www.informatimago.com/



More information about the armedbear-devel mailing list