Hi Tom,<br><br><div class="gmail_quote">On Wed, Oct 13, 2010 at 8:07 AM, Tom Rushworth <span dir="ltr">&lt;<a href="mailto:tom_rushworth@mac.com">tom_rushworth@mac.com</a>&gt;</span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
Hi all,<br>
<br>
Take a look through the literature for the &quot;strength&quot; of the various types of atomic operations with respect to doing various synchronization tasks.  CAS is &quot;universal&quot; in the sense that it can simulate all of the others.  (The simulation is wretched, O(N**3), so it isn&#39;t practical, but...)<br>

I doubt that your atomic swap is as strong.<br>
<br>
Pretty well every current HW architecture actually has the CAS instruction (or some minor variation) implemented as a single instruction, so making it a primitive should be relatively easy. It seems a terrible waste to pick a weak synchronization primitive when a much better one could be had for very little more work.<br>

<div class="im"><br>
On 2010-Oct-12, at 12:04, Igor Stasenko wrote:<br>
<br>
&gt; CAS? Perhaps. If you wish to add it too, no problem.<br>
&gt;<br>
&gt; I want at minimum swap, because with it i can easily implement<br>
&gt; lock-free waiting:<br>
&gt;<br>
&gt; [ | temp |<br>
&gt;  [ locked ] whileTrue.<br>
&gt;    temp := true.<br>
&gt;    locked :=: temp.<br>
&gt;    temp<br>
&gt; ] whileTrue.<br>
<br>
</div>I think this is simpler (using Eliot&#39;s notation):<br>
<br>
  [locked ?:= true : false] whileFalse.<br>
<br>
   ... locked here ...<br>
<br>
   locked := false.<br>
<br>
No temp needed, single block. well understood atomic op :).<br>
I&#39;ve used this pattern (expressed in C code) in a very heavily used parallel data processing application, so I can even claim to have tested it extensively :).<br></blockquote><div><br></div><div>Right.  And because Smalltak can&#39;t reify variables and CAS is an operation on a variable CAS can&#39;t be implemented as a primitive on variables.  There&#39;s no way to express &quot;pass a variable to a primitive&quot;, only &quot;pass an expression (which may be the value of a variable)&quot; to a primitive&quot;.  One could do it with a primitive on an object, e.g. thisContext at: tempIndex compareWith: match andSetTo: expr, or anObject instVarAt: varIndex compareWith: match andSetTo: expr but that&#39;s soooo ugly.  Hence I think it is better done using a special assignment operator.</div>
<div><br></div><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>
&gt;<br>
&gt; ... locked here ...<br>
&gt;<br>
&gt; locked := false.<br>
&gt;<br>
&gt; Proof:<br>
&gt; In the above, thread having chance to exit from waiting loop only if<br>
&gt; temp == false.<br>
&gt; There is no way how more than one waiting threads can leave this loop<br>
&gt; at same time,<br>
&gt; because &#39;locked&#39; value is not copied over (assigned) but swapped<br>
&gt; (always with true).<br>
&gt; So, first who succeed to swap  false &lt;-&gt; true will obtain a lock,<br>
&gt; others will unable to do so, and swap true&lt;-&gt;true, and thus will keep<br>
&gt; waiting in the loop.<br>
&gt;<br>
&gt;<br>
&gt; On 12 October 2010 20:46, Eliot Miranda &lt;<a href="mailto:eliot.miranda@gmail.com">eliot.miranda@gmail.com</a>&gt; wrote:<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt; On Tue, Oct 12, 2010 at 8:28 AM, Tom Rushworth &lt;<a href="mailto:tom_rushworth@mac.com">tom_rushworth@mac.com</a>&gt;<br>
&gt;&gt; wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; If you&#39;re going for atomic swap as a primitive, why not go for<br>
&gt;&gt;&gt; Compare-And-Swap?  That way all the various lock-free algorithms that use<br>
&gt;&gt;&gt; the CAS machine instruction will translate easily.<br>
&gt;&gt;<br>
&gt;&gt; +1.<br>
&gt;&gt; I want, e.g.<br>
&gt;&gt;        (var ?== expr : match) evaluates to true and var == expr if var ==<br>
&gt;&gt; prev before the statement, and false and var unchanged if var ~~ match<br>
&gt;&gt; var ?= expr : match is more difficult to implement since = is not<br>
&gt;&gt; necessarily primitive.<br>
&gt;&gt; So one could write e.g.<br>
&gt;&gt; LinkedList subclass: #Semaphore<br>
&gt;&gt;     instanceVariableNames: &#39;signals locked&#39;<br>
&gt;&gt; Semaphore&gt;&gt;signal<br>
&gt;&gt;     [locked ?== true : false] whileFalse.<br>
&gt;&gt;     self isEmpty<br>
&gt;&gt;         ifTrue: [signals := signals + 1]<br>
&gt;&gt;         ifFalse: [self removeFirst resume].<br>
&gt;&gt;     locked := false<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; CAS(variable,oldValue,newValue) is an atomic operation which returns a<br>
&gt;&gt;&gt; boolean value (my ST syntax is rusty at the moment, too much Objective-C):<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; (variable == oldValue) ifTrue: [variable := newValue. ^true].<br>
&gt;&gt;&gt; &quot; variable not the same as oldValue, no swap performed &quot;<br>
&gt;&gt;&gt; ^false<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; On 2010-Oct-12, at 06:58, Igor Stasenko wrote:<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; On 12 October 2010 16:51, Levente Uzonyi &lt;<a href="mailto:leves@elte.hu">leves@elte.hu</a>&gt; wrote:<br>
&gt;&gt;&gt;&gt;&gt; On Tue, 12 Oct 2010, Igor Stasenko wrote:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; Hello, i just thought, that it would be cool to have a special<br>
&gt;&gt;&gt;&gt;&gt;&gt; bytecode,<br>
&gt;&gt;&gt;&gt;&gt;&gt; which guarantees atomicity for swapping values between two variables.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; To swap two values, you usually do:<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; | var1 var2 temp |<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; temp := var1.<br>
&gt;&gt;&gt;&gt;&gt;&gt; var1 := var2.<br>
&gt;&gt;&gt;&gt;&gt;&gt; var2 := temp.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; But since its non-atomic, a process can be interrupted and such<br>
&gt;&gt;&gt;&gt;&gt;&gt; operation<br>
&gt;&gt;&gt;&gt;&gt;&gt; is not thread-safe.<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; In order to make it thread safe, you must add even more boilerplate:<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; | var1 var2 temp |<br>
&gt;&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt;&gt; semaphore critical: [<br>
&gt;&gt;&gt;&gt;&gt;&gt;  temp := var1.<br>
&gt;&gt;&gt;&gt;&gt;&gt;  var1 := var2.<br>
&gt;&gt;&gt;&gt;&gt;&gt;  var2 := temp.<br>
&gt;&gt;&gt;&gt;&gt;&gt; ]<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; An alternative solution:<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; | a b |<br>
&gt;&gt;&gt;&gt;&gt; a := 1.<br>
&gt;&gt;&gt;&gt;&gt; b := 2.<br>
&gt;&gt;&gt;&gt;&gt; [<br>
&gt;&gt;&gt;&gt;&gt;        | tmp |<br>
&gt;&gt;&gt;&gt;&gt;        tmp := a.<br>
&gt;&gt;&gt;&gt;&gt;        a := b.<br>
&gt;&gt;&gt;&gt;&gt;        b := tmp ] valueUnpreemptively<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; Yeah, another boilerplate under the hood, also highly dependent from<br>
&gt;&gt;&gt;&gt; scheduling nuances :)<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; valueUnpreemptively<br>
&gt;&gt;&gt;&gt;       &quot;Evaluate the receiver (block), without the possibility of<br>
&gt;&gt;&gt;&gt; preemption<br>
&gt;&gt;&gt;&gt; by higher priority processes. Use this facility VERY sparingly!&quot;<br>
&gt;&gt;&gt;&gt;       &quot;Think about using Block&gt;&gt;valueUninterruptably first, and think<br>
&gt;&gt;&gt;&gt; about<br>
&gt;&gt;&gt;&gt; using Semaphore&gt;&gt;critical: before that, and think about redesigning<br>
&gt;&gt;&gt;&gt; your application even before that!<br>
&gt;&gt;&gt;&gt;       After you&#39;ve done all that thinking, go right ahead and use it...&quot;<br>
&gt;&gt;&gt;&gt;       | activeProcess oldPriority result |<br>
&gt;&gt;&gt;&gt;       activeProcess := Processor activeProcess.<br>
&gt;&gt;&gt;&gt;       oldPriority := activeProcess priority.<br>
&gt;&gt;&gt;&gt;       activeProcess priority: Processor highestPriority.<br>
&gt;&gt;&gt;&gt;       result := self ensure: [activeProcess priority: oldPriority].<br>
&gt;&gt;&gt;&gt;       &quot;Yield after restoring priority to give the preempted processes a<br>
&gt;&gt;&gt;&gt; chance to run&quot;<br>
&gt;&gt;&gt;&gt;       Processor yield.<br>
&gt;&gt;&gt;&gt;       ^result<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;&gt; Levente<br>
&gt;&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;&gt; --<br>
&gt;&gt;&gt;&gt; Best regards,<br>
&gt;&gt;&gt;&gt; Igor Stasenko AKA sig.<br>
&gt;&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt; --<br>
&gt;&gt;&gt; Tom Rushworth<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;&gt;<br>
&gt;<br>
&gt;<br>
&gt;<br>
&gt; --<br>
&gt; Best regards,<br>
&gt; Igor Stasenko AKA sig.<br>
&gt;<br>
<br>
</div></div>--<br>
<font color="#888888">Tom Rushworth<br>
<br>
<br>
<br>
<br>
</font></blockquote></div><br>