and here's a version with a better class comment

On Thu, Jan 7, 2016 at 9:12 AM, Eliot Miranda <eliot.miranda@gmail.com> wrote:
Hi Denis, Hi Cl��ment, ��Hi Frank,

On Thu, Jan 7, 2016 at 5:34 AM, Cl��ment Bera <bera.clement@gmail.com> wrote:
Hello,

Eliot, please, you told me you had the code and Denis is interested.

It uses 3 primitives for performance.

Forgive the delay.�� I thought it proper to ask permission since the code was written while I was at Qwaq. I'm attaching the code in a fairly raw state, see the attached.�� The code is MIT, but copyright 3DICC.

It is a plugin replacement for Squeak's Mutex, and with a little ingenuity could be a replacement for Squeak's Monitor.�� It is quicker because it uses three new primitives to manage entering a critical section and setting the owner, exiting the critical section and releasing the owner, and testing if a��critical��section, entering if the section is unowned.�� The use of the primitives means fewer block activations and ensure: blocks in entering and exiting the critical section, and that's the actual cause of the speed-up.

You can benchmark the code as is.�� Here are some results on 32-bit Spur, on my 2.2GHz Core i7

{Mutex new. Monitor new. CriticalSection new} collect:
[:cs| | n |
n := 0.
[cs critical: [n := n + 1]. cs critical: [n := n + 1]. cs critical: [n := n + 1]. cs critical: [n := n + 1]. cs critical: [n := n + 1].
cs critical: [n := n - 1]. cs critical: [n := n - 1]. cs critical: [n := n - 1]. cs critical: [n := n - 1]. cs critical: [n := n - 1].
n ] bench]

{Mutex new. Monitor new. CriticalSection new} collect:
[:cs| | n |
n := 0.
cs class name, ' -> ',
[cs critical: [n := n + 1]. cs critical: [n := n + 1]. cs critical: [n := n + 1]. cs critical: [n := n + 1]. cs critical: [n := n + 1].
cs critical: [n := n - 1]. cs critical: [n := n - 1]. cs critical: [n := n - 1]. cs critical: [n := n - 1]. cs critical: [n := n - 1].
n ] bench]

#( 'Mutex -> 440,000 per second. 2.27 microseconds per run.'
'Monitor -> 688,000 per second. 1.45 microseconds per run.'
'CriticalSection -> 1,110,000 per second. 900 nanoseconds per run.')

Replacement is probably trivial; rename Mutex to OldMutex, rename CriticalSection to Mutex, recompile.�� But there are lots of mutexes in the system and these are potentially owned.�� Transforming unowned ones is trivial, but transforming owned ones is, I think, impossible.�� But at least in my system there are no owned mutexes or monitors.

Frank (or anyone else), would you be interested in creating a replacement for Squeak's Monitor based on CriticalSection?


Here are the two business methods:
CriticalSection methods for mutual exclusion
critical: aBlock
"Evaluate aBlock protected by the receiver."
^self primitiveEnterCriticalSection
ifTrue: [aBlock value]
ifFalse: [aBlock ensure: [self primitiveExitCriticalSection]]

critical: aBlock ifLocked: lockedBlock
"Answer the evaluation of aBlock protected by the receiver.�� If it is already in a critical
section on behalf of some other process answer the evaluation of lockedBlock."
^self primitiveTestAndSetOwnershipOfCriticalSection
ifNil: [lockedBlock value]
ifNotNil:[:alreadyOwner|
alreadyOwner
ifTrue: [aBlock value]
ifFalse: [aBlock ensure: [self primitiveExitCriticalSection]]]

and the primitives:
CriticalSection methods for private-primitives
primitiveEnterCriticalSection
"Primitive. The receiver must be unowned or owned by the current process to proceed.
Answer if the process is owned by the current process."
<primitive: 186>
self primitiveFailed
"In the spirit of the following"
"[owner ifNil:
[owner := Processor activeProcess.
^false].
��owner = Processor activeProcess ifTrue:
[^true].
��self addLast: Processor activeProcess.
��Processor activeProcess suspend] valueUnpreemptively"

primitiveExitCriticalSection
"Primitive. Set te receiver to unowned and if any processes are waiting on
the receiver then proceed the first one, indicating that the receiver is unowned."
<primitive: 185>
self primitiveFailed
"In the spirit of the following"
"[owner := nil.
��self isEmpty ifFalse:
[process := self removeFirst.
process resume]] valueUnpreemptively"

primitiveTestAndSetOwnershipOfCriticalSection
"Primitive. Attempt to set the ownership of the receiver.
If the receiver is unowned set its owningProcess to the
activeProcess and answer false.�� If the receiver is owned
by the activeProcess answer true.�� If the receiver is owned
by some other process answer nil."
<primitive: 187>
self primitiveFail
"In the spirit of the following"
"[owner ifNil:
[owningProcess := Processor activeProcess.
^false].
��owner = Processor activeProcess ifTrue: [^true].
��^nil] valueUnpreemptively"

2016-01-07 13:24 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com>:
��
Hello.

I hear about new Monitor implementation based on new primitives.
Where to get it?

_,,,^..^,,,_
best,��Eliot



--
_,,,^..^,,,_
best,��Eliot