From: Christopher N. <cjn...@cn...> - 2005-08-23 15:33:53
|
On Mon, 22 Aug 2005 17:33:34 +0300 (EEST), Nikodemus Siivola <nik...@ra...> said: > On Mon, 22 Aug 2005, Christopher Neufeld wrote: >> Anyway, I'm happy with the behaviour, if it can be documented. The >> construct I provided seemed natural, and almost did the right thing, but > Documentation patches welcome. OK, here's my proposed patch: --- src/code/target-thread.lisp.orig Mon Aug 22 06:19:44 2005 +++ src/code/target-thread.lisp Tue Aug 23 10:47:04 2005 @@ -459,7 +459,28 @@ (defun make-thread (function &key name) #!+sb-doc "Create a new thread of NAME that runs FUNCTION. When the function -returns the thread exits." +returns the thread exits. + +It is important to note that if FUNCTION is a lambda expression +which depends on variables in the lexical environment, that the values +of those variables are not evaluated immediately, but only at some +later time when the thread begins to execute. Consequently, the +following code may print the number 2 twice: + + (let ((i 1)) + (make-thread (lambda () (format t \"~d~%\" i))) + (incf i) + (format t \"~d~%\" i)) + +The correct solution is to create new closures around the call(s) to +MAKE-THREAD, protecting the variables used against changes made by the +calling context: + + (let ((i 1)) + (let ((i-local i)) + (make-thread (lambda () (format t \"~d~%\" i-local)))) + (incf i) + (format t \"~d~%\" i))" #!-sb-thread (declare (ignore function name)) #!-sb-thread (error "Not supported in unithread builds.") #!+sb-thread -- Christopher Neufeld Home page: http://www.cneufeld.ca/neufeld "Don't edit reality for the sake of simplicity" |