From: Peter Seibel
Subject: Closures and multithreading?
Date: 
Message-ID: <m38yu8beub.fsf@javamonkey.com>
I skimmed through the Allegro multiprocessing/multithreading docs but
didn't find any discussion of this. And I'm interested in how other
implementations handle it too. Suppose I have some code like:

  (let ((x 10))
    (mp:process-run-function "my-process"
      #'(lambda () (dotimes (i 10) (incf x))))
    (dotimes (i 10) (princ x)))
 

(Not meant to be ACL specific though I'm using their function name.)
I.e. I spin up a thread to run a function which closes over X and
modifies it. Meanwhile the original thread continues to observe the
value. Is this legal? If so, what, if anything, is guaranteed about
the values of X--can they be garbage, or will they always be values
actually stored into X?

Assuming that kind of cross-thread closure is possible I assume to
write this correctly I'd need to do something like:

  (let ((x 10)
        (lock (mp:make-process-lock)))
    (mp:process-run-function "my-process"
      #'(lambda ()
          (dotimes (i 10)
            (mp:with-process-lock (lock) (incf x)))))
    (dotimes (i 10)
      (mp:with-process-lock (lock) (princ x))))

-Peter

-- 
Peter Seibel                                      ·····@javamonkey.com

  The intellectual level needed   for  system design is  in  general
  grossly  underestimated. I am  convinced  more than ever that this
  type of work is very difficult and that every effort to do it with
  other than the best people is doomed to either failure or moderate
  success at enormous expense. --Edsger Dijkstra

From: Jock Cooper
Subject: Re: Closures and multithreading?
Date: 
Message-ID: <m38yu7buyl.fsf@jcooper02.sagepub.com>
Peter Seibel <·····@javamonkey.com> writes:

> I skimmed through the Allegro multiprocessing/multithreading docs but
> didn't find any discussion of this. And I'm interested in how other
> implementations handle it too. Suppose I have some code like:
> 
>   (let ((x 10))
>     (mp:process-run-function "my-process"
>       #'(lambda () (dotimes (i 10) (incf x))))
>     (dotimes (i 10) (princ x)))
>  
> 
> (Not meant to be ACL specific though I'm using their function name.)
> I.e. I spin up a thread to run a function which closes over X and
> modifies it. Meanwhile the original thread continues to observe the
> value. Is this legal? If so, what, if anything, is guaranteed about
> the values of X--can they be garbage, or will they always be values
> actually stored into X?
> 
> Assuming that kind of cross-thread closure is possible I assume to
> write this correctly I'd need to do something like:
> 
>   (let ((x 10)
>         (lock (mp:make-process-lock)))
>     (mp:process-run-function "my-process"
>       #'(lambda ()
>           (dotimes (i 10)
>             (mp:with-process-lock (lock) (incf x)))))
>     (dotimes (i 10)
>       (mp:with-process-lock (lock) (princ x))))
> 

That has always been my assumption;  I have a fair amount of code 
does exactly this type of thing.  Anytime I have multiple processes
sharing some data element (usually lists of rows from a database)
I wrap it in a with-process-lock.  

Jock Cooper
http://www.fractal-recursions.com
From: Edi Weitz
Subject: Re: Closures and multithreading?
Date: 
Message-ID: <87he8vlhy4.fsf@bird.agharta.de>
Peter Seibel <·····@javamonkey.com> writes:

> I skimmed through the Allegro multiprocessing/multithreading docs
> but didn't find any discussion of this. And I'm interested in how
> other implementations handle it too. Suppose I have some code like:
> 
>   (let ((x 10))
>     (mp:process-run-function "my-process"
>       #'(lambda () (dotimes (i 10) (incf x))))
>     (dotimes (i 10) (princ x)))
>  
> 
> (Not meant to be ACL specific though I'm using their function name.)
> I.e. I spin up a thread to run a function which closes over X and
> modifies it. Meanwhile the original thread continues to observe the
> value. Is this legal? If so, what, if anything, is guaranteed about
> the values of X--can they be garbage, or will they always be values
> actually stored into X?
> 
> Assuming that kind of cross-thread closure is possible I assume to
> write this correctly I'd need to do something like:
> 
>   (let ((x 10)
>         (lock (mp:make-process-lock)))
>     (mp:process-run-function "my-process"
>       #'(lambda ()
>           (dotimes (i 10)
>             (mp:with-process-lock (lock) (incf x)))))
>     (dotimes (i 10)
>       (mp:with-process-lock (lock) (princ x))))

I think the answer is "it depends" because it's not governed by the
ANSI standard although most implementations might behave similar. 

Nick Levine has written something about how LW handles it here:

  <http://cl-cookbook.sourceforge.net/process.html>

Specifically, search for the headline "Closures! Warning!".

Cheers,
Edi.