David Kirkman dkirkman@ucsd.edu writes:
On Sat, Apr 24, 2010 at 7:50 AM, Erik Huelsmann ehuels@gmail.com wrote:
Can you share some examples which show the issues here? Adding thread-safety to clos.lisp - in specific, targeted places - should be well doable.
It was surprisingly difficult to create a fragment which would reproduce the errors. But here it is!
(defclass counter () ((count :initform 0)))
(setf *ncount* 10000) (setf *nthread* 1000)
(defun count-thread (amount) #'(lambda () (let ((c (make-instance 'counter))) (dotimes (i *ncount*) (incf (slot-value c 'count) amount)) (format t "count ~A = ~A~%" amount (slot-value c 'count)))))
(dotimes (i *nthread*) (threads:make-thread (count-thread i)))
On my machine, a half dozen or so threads will reliably die with either:
Missing slot MOP::NAME
or
Missing slot MOP::PRECEDENCE-LIST
The MOP::NAME error has about 5x more common than the MOP::PRECEDENCE-LIST error. The key to reproducing the error is to use a lot of threads, with *nthread* = 2, the code can run all morning without any trouble. But it will eventually give an error: I originally noticed this with long running code and two threads. Even with *nthread* = 10, it works without error most of the time.
It also works (I mean gives errors) if you drop the final format in count-thread. The format is not thread safe, but it does not seem to cause errors by itself -- it just mangles output -- and it helps to see which threads are finishing.
There's a trick against the mangling. Use
(fresh-line) (write-line (format nil <fmt-ctrl> . <fmt-args>))
HTH
-T.