Cross platform atomicity of #ifNil:

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
3 messages Options
Reply | Threaded
Open this post in threaded view
|

Cross platform atomicity of #ifNil:

Ben Coman

I am looking at dealing with multiple in-image threads and am wondering
about what operations are atomic.  The current understanding is that...
    (myvar == nil) ifTrue: [ myvar := 1.  myvar2 := #something ]
is atomic, but I see some indication in comments (sorry lost my
reference) that...
    myvar ifNil: [ myvar:=1 ]
might not be - but maybe those comments were historical. What is the
current status and likely future guarantees for Squeak/Pharo/Cuis/other?

cheers -ben

Reply | Threaded
Open this post in threaded view
|

Re: Cross platform atomicity of #ifNil:

J. Vuletich (mail lists)
Hi Ben,

Quoting Ben Coman <[hidden email]>:

> I am looking at dealing with multiple in-image threads and am  
> wondering about what operations are atomic.  The current  
> understanding is that...
>    (myvar == nil) ifTrue: [ myvar := 1.  myvar2 := #something ]
> is atomic, but I see some indication in comments (sorry lost my  
> reference) that...
>    myvar ifNil: [ myvar:=1 ]
> might not be - but maybe those comments were historical.

That was true when ifNil: was a conventional message send. For quite  
some time it has been optimized by the compiler (In Cuis for sure,  
most likely also in Squeak and Pharo). The way to know for sure is to  
check the generated bytecodes.

> What is the current status and likely future guarantees for  
> Squeak/Pharo/Cuis/other? cheers -ben

Any point where there is a real message send, the active process could  
be suspended. It can also happen when there is a backward jump. This  
behavior is in the VM. So, for guarantees about the future, you need  
to check for changes on:

- VM suspension points. Eliot said "A process can only be suspended on  
method activation (a non-primitive method activation, or primitive  
failure) or on backward branch." Maybe he can comment on whether there  
is any possibility of needing to change this in the future.

- Compiler optimization of #ifNil: and friends. Most likely this won't  
ever change in Squeak and Cuis. In Pharo there is a newer compiler  
(not sure if it optimizes #ifNil:), and in general there are more and  
deeper changes in these kernel parts of the system. So maybe it is  
wise to stay tuned. In any case, it is not likely that this would  
change without you knowing about it.

Cheers,
Juan Vuletich


Reply | Threaded
Open this post in threaded view
|

Re: [Vm-dev] Cross platform atomicity of #ifNil:

Eliot Miranda-2
In reply to this post by Ben Coman


On Thu, Aug 7, 2014 at 10:00 PM, Ryan Macnak <[hidden email]> wrote:
 
On Thu, Aug 7, 2014 at 8:43 PM, Ben Coman <[hidden email]> wrote:
I am looking at dealing with multiple in-image threads and am wondering about what operations are atomic.  The current understanding is that...
   (myvar == nil) ifTrue: [ myvar := 1.  myvar2 := #something ]
is atomic, but I see some indication in comments (sorry lost my reference) that...
   myvar ifNil: [ myvar:=1 ]
might not be - but maybe those comments were historical. What is the current status and likely future guarantees for Squeak/Pharo/Cuis/other?

On Squeak-derived systems the two operations that are not atomic are message sends and backward branches; these are where the VM checks for external events and your process might be preempted by one with a higher priority.

That's very close.  In fact, the two places where the VM tests for events are sends that build a frame and backward branches.  So a send that activates a method that has a primitive that doesn't fail won't check for events.  Quick primitives are used to answer inst vars of all objects except contexts, so any inst var fetch of a non-context can be done without a process switch.
 
#ifTrue: and #ifNil: are atomic because the bytecode compiler inlines them (#ifTrue: has always been inlined, but I don't think #ifNil: always was).

That's right.
 
#== is atomic because the VM implements it without a send.
 
And it would still be atomic if sent since it will bind to a non-failing primitive.

This is all if code runs normally. If run through the debugger you might be interrupted at any operation because the simulation is implemented in terms of Smalltalk code with tons of sends. One should not rely on these implementation details and instead use semaphores or (very rarely) #valueUnpreemptively.

It's very useful for experiments to know what one can get away with.  But the language could add some atomicity operation such as conditional assignment, and that could still be safe if debugged. e.g. (myVar ?== nil := 1) would be a nice syntax, setting myVar to 1 if it is == to nil.  Nice too if this evaluated to a boolean, true if the assignment occurred.

--
best,
Eliot