Great, thanks!<br><br><div class="gmail_quote">On Sun, Oct 18, 2009 at 7:09 PM, Gary Byers <span dir="ltr"><<a href="mailto:gb@clozure.com">gb@clozure.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
<div><div></div><div class="h5"><br>
<br>
On Sun, 18 Oct 2009, David L. Rager wrote:<br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hi,<br>
One more hopefully quick question about atomic-incf/atomic-decf:<br>
<br>
Can the return value of an atomic-incf/decf be relied upon as the value<br>
right after that particular incf occurrs?  Given it's a compare and swap,<br>
I'm guessing that the answer to this question is "yes".<br>
<br>
Another way to ask the same question is, if I perform two atomic-incf's in a<br>
row (i.e., as simultaneously as the x86 platform will allow me), will one of<br>
the atomic-incf calls return the intermediate value, and the other<br>
atomic-incf return the newest value?<br>
<br>
E.g.:<br>
A long time ago, in some thread far far away:<br>
(defvar *x* 3)<br>
<br>
In a current time, with two concurrent threads<br>
<br>
Thread A:<br>
(atomic-incf *x*) ; sets *x* to 4, returns 4<br>
<br>
Thread B:<br>
(atomic-incf *x*) ; sets *x* to 5, returns 5<br>
<br>
Of course if Thread B occurred before Thread A, the B transcript would have<br>
"sets *x* to 4, returns 4" and the A transcript would also change to use the<br>
number 5.<br>
<br>
</blockquote>
<br></div></div>
Yes; after these two ATOMIC-INCFs complete, *X* will have the value 5,<br>
and the return value of each ATOMIC-INCF will be the value stored in<br>
the location at the time that it was successfully stored.  (That may<br>
or may not be the same as "the contents of *X* by the time that you<br>
can observe it.")<br>
<br>
The code behaves something like:<br>
<br>
(loop<br>
  (let* ((old-value (contents-of loc))<br>
         (new-value (1+ old-value))<br>
         (win nil))<br>
   (with-bus-locked<br>
     (when (= (contents-of loc) old-value)  ; this is just compare-and-swap<br>
       (setf (contents-of loc) new-value<br>
             win t)))<br>
   (if win (return new-value))))<br>
<br>
where WITH-BUS-LOCKED is supposed to suggest some sort of hardware-imposed<br>
atomicity and memory-ordering (the "lock" prefix on x86, cache-line reservations<br>
and memory barriers on PPC, etc.)<br>
<br>
This is a pretty obscure thing to note, but note that the compare-and-swap<br>
doesn't quite guarantee that the location hasn't changed: it's possible that<br>
it was incremented and decremented between the time it was read (at the top<br>
of the loop) and the time that it was tested by compare-and-swap.  In a lot<br>
of cases this doesn't matter; in some cases, it might.  (I think that that's<br>
known as the "ABA" problem, where a memory location's contents change from<br>
A to B and back to A; I know that it comes up, but don't remember canonical<br>
examples that demonstrate cases where it matters.)<div><div></div><div class="h5"><br>
<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">
Hopefully between my two versions of the question, my real question is<br>
clear.<br>
<br>
Thanks,<br>
David<br>
<br>
</blockquote>
</div></div></blockquote></div><br>