Hello my name is Sebastián Krynski from Buenos Aires, Argentina. Just writing to let you know that I'm starting to work on adding an atomic swap operator in Pharo , guaranteed not to be interrupted by the VM. The operator will be used this way: a :=: b meaning 'swap variable a with variable b'. In order to do this I will be modifying the VM and the Compiler . I'm working under the direction of INRIA and Gabriela Arévalo. |
Sound cool! But isn’t that the same as a become: b ? I even think that tmp := a. a := b. b := tmp is equivalent, since the VM only interrupts message sends, and in this case only byte code would be generated? That’s not my area of expertise, so please correct me. Cheers, Max
|
Hello, If the operator is atomic that means if another thread (I am talking about native threads) interacts with the same portion of memory than the active thread its operation will be done after of before. This is a step toward a multithreaded VM with lock free algorithms and is different from just having a user interrupt or a process switch. #become: or the multiple assignments you showed are done in several cpu instructions hence another thread can manipulate the same memory while the operation is performed, which is not atomic. Hence, the way I understand it is that the operation :=: is done in 1 cpu instruction. Sebastián has to change the bytecode compiler, the JIT and the interpreter to support that. That cannot be done with any variable, but it may be possible to implement :=: for at least 2 temporaries using the cpu swap. There is still a long way to go to have a multithreaded VM with lock-free algorithms, but one has to start somewhere I guess. I am not expert in concurrent programming but atomic swap or test and set operations are probably the way to go. Cheers, Clement 2015-10-12 14:12 GMT+02:00 Max Leske <[hidden email]>:
|
I see. That does make sense. Thanks Clement.
|
In reply to this post by skrynski
Hi Sebastiàn,
2015-10-12 13:53 GMT+02:00 Sebastián Krynski <[hidden email]>:
Why a cryptic, special syntax? The compiler could inline an explicit message send which would make the intent clear. a atomicSwapWith: b. Well, anyway, the compiler has to do something special there. Could we have something like... [ | temp | temp := a. a := b. b := a ] atomic ? Would a compiler be able to merge that in a swap instruction? And make another type of processing for a different code inside the block?
Good luck. This is an important step.
Welcome! Thierry |
On Mon, Oct 12, 2015 at 3:20 PM, Thierry Goubier <[hidden email]> wrote:
See previous discussions about <=> indeed.
We have Mutex>>critical: aBlock etc. Why not Atomic>>do: aBlock ? Would indeed be more readable than :=: Phil
|
2015-10-12 15:33 GMT+02:00 [hidden email] <[hidden email]>:
Honestly this block followed by atomic is very confusing IMO. That means that the compiler has to raise an error if it did not succeed to compile the block in a single cpu instruction, i.e., a single bytecode that compiles to a single cpu instruction. For example: [ | temp | temp := a. a := b. b := a. self foo ] atomic has to raise a compilation error as the block cannot be compiled in a single instruction. Overall very few instructions in specific order can be compiled in a such a block. Atomic>>#do: can work but the argument block needs to be compiled in a single instruction so the bytecode compiler has to aware of the syntax based on the selector anyway. For example, in: anAtomic do: [ | temp | temp := a. a := b. b := a ] then the compiler has to compile the block specifically to have single instruction, even if the call to anAtomic is done in the runtime. On the other hand a new special selector as #atomicSwapWith:, in a similar way to #ifTrue:ifFalse:, is definitely doable and easy to implement. If you think it's more readable then it's the way to go. It does not extend the syntax so I think it can be done like that for the experiment as it is simpler to implement.
|
2015-10-12 16:46 GMT+02:00 Clément Bera <[hidden email]>:
Oh, Clement, compilers can do a lot more than that ;) This one would be easy to do, even if a bit ad-hoc (it's just a simple refactoring pattern to recognize, after all). Let me see... '[ | `x | `x := `y. `y := `z. `z := `x] atomic' RBParseTreeSearcher treeMatching: '[ | `x | `x := `y. `y := `z. `z := `x]' in: (RBParser parseExpression: '[ | temp | temp := a. a := b. b := temp ] atomic') Note that it fails on all the wrong variants you wrote, which leads me to spend more time if I got my pattern right :( But I was considering that it would be either an atomic swap (if the compiler recognize the sequence ... I usually see test_and_set as the primitive, and nowadays everybody saying transactional memory instructions are the way to go) or a critical if it can't be compiled as an atomic instruction (in short, same semantics? but different speeds... I think the trade-off is acceptable)
Same as the atomic case above. Atomic should be a singleton; no need to create instances of Atomic, even conceptually.
I think this is an important point. Marcus, can something special like that be done via a compiler plugin or a MetaLink? This would be really convenient. Thierry
|
Free forum by Nabble | Edit this page |