<br><br><div class="gmail_quote">On Wed, Oct 13, 2010 at 11:53 AM, Igor Stasenko <span dir="ltr"><<a href="mailto:siguctua@gmail.com">siguctua@gmail.com</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex;">
2010/10/13 Levente Uzonyi <<a href="mailto:leves@elte.hu">leves@elte.hu</a>>:<br>
<div><div></div><div class="h5">> On Tue, 12 Oct 2010, Igor Stasenko wrote:<br>
><br>
>> On 12 October 2010 16:51, Levente Uzonyi <<a href="mailto:leves@elte.hu">leves@elte.hu</a>> wrote:<br>
>>><br>
>>> On Tue, 12 Oct 2010, Igor Stasenko wrote:<br>
>>><br>
>>>> Hello, i just thought, that it would be cool to have a special bytecode,<br>
>>>> which guarantees atomicity for swapping values between two variables.<br>
>>>><br>
>>>> To swap two values, you usually do:<br>
>>>><br>
>>>> | var1 var2 temp |<br>
>>>><br>
>>>> temp := var1.<br>
>>>> var1 := var2.<br>
>>>> var2 := temp.<br>
>>>><br>
>>>> But since its non-atomic, a process can be interrupted and such<br>
>>>> operation<br>
>>>> is not thread-safe.<br>
>>>><br>
>>>> In order to make it thread safe, you must add even more boilerplate:<br>
>>>><br>
>>>> | var1 var2 temp |<br>
>>>><br>
>>>> semaphore critical: [<br>
>>>> temp := var1.<br>
>>>> var1 := var2.<br>
>>>> var2 := temp.<br>
>>>> ]<br>
>>><br>
>>> An alternative solution:<br>
>>><br>
>>> | a b |<br>
>>> a := 1.<br>
>>> b := 2.<br>
>>> [<br>
>>> | tmp |<br>
>>> tmp := a.<br>
>>> a := b.<br>
>>> b := tmp ] valueUnpreemptively<br>
>>><br>
>><br>
>> Yeah, another boilerplate under the hood, also highly dependent from<br>
>> scheduling nuances :)<br>
><br>
> I don't get the "dependency from scheduling nuances part", but here's my<br>
> idea:<br>
<br>
</div></div>i don't like the code, which assuming that scheduling works in some<br>
specific way,<br>
or some code can't be interrupted in the middle.<br>
<br>
See Semaphore>>critical: for excersise.<br>
<br>
| caught |<br>
caught := false.<br>
^[<br>
caught := true.<br>
self wait.<br>
mutuallyExcludedBlock value<br>
] ensure: [ caught ifTrue: [self signal] ]<br>
<br>
this code assuming that between<br>
caught := true.<br>
and<br>
self wait.<br>
<br>
no interrupt possible.<br>
But if it is, then the above implementation is incorrect.<br>
<div class="im"><br>
<br>
><br>
> Add the compiler changes to support :=: as atomic swap. We don't really need<br>
> a bytecode for now, since a sequence of assignments is currently atomic. So<br>
> the compiler could compile :=: as three assignments using a hidden temporary<br>
> variable. On other systems, :=: can be compiled differently.<br>
><br>
<br>
</div>For same reason, there is no any guarantees from VM side that three<br>
assignments in a row will be<br>
atomic: storing pointer could trigger a root check, and if roots table<br>
is full, it could trigger GC,<br>
and after GC, there is a finalization semaphore, which could switch an<br>
active process immediately.<br>
<br>
VM is evolving and subject to change. Having a clear rule which<br>
guarantees a specific behavior is far more<br>
beneficial comparing to intimate knowledge about how VM works (now).<br></blockquote><div><br></div><div>+1. I think there's general agreement on this. All this uninterruptibiity goes out of the window (as does Processor activeProcess) as soon as anyone does a truly concurrent implementation.</div>
<div><br></div><div>best</div><div>Eliot </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>
<br>
><br>
> Levente<br>
><br>
>><br>
>> valueUnpreemptively<br>
>> "Evaluate the receiver (block), without the possibility of<br>
>> preemption<br>
>> by higher priority processes. Use this facility VERY sparingly!"<br>
>> "Think about using Block>>valueUninterruptably first, and think<br>
>> about<br>
>> using Semaphore>>critical: before that, and think about redesigning<br>
>> your application even before that!<br>
>> After you've done all that thinking, go right ahead and use it..."<br>
>> | activeProcess oldPriority result |<br>
>> activeProcess := Processor activeProcess.<br>
>> oldPriority := activeProcess priority.<br>
>> activeProcess priority: Processor highestPriority.<br>
>> result := self ensure: [activeProcess priority: oldPriority].<br>
>> "Yield after restoring priority to give the preempted processes a<br>
>> chance to run"<br>
>> Processor yield.<br>
>> ^result<br>
>>><br>
>>> Levente<br>
>>><br>
>><br>
>><br>
>><br>
>> --<br>
>> Best regards,<br>
>> Igor Stasenko AKA sig.<br>
>><br>
><br>
><br>
><br>
><br>
<br>
<br>
<br>
--<br>
Best regards,<br>
Igor Stasenko AKA sig.<br>
<br>
</div></div></blockquote></div><br>