Hi.
We got interesting discussion about semaphore and mutex.
Here I put summary of proposed changes.
First we will deprecate��Semaphore>>forMutualExclusion
and rename it to Semaphore>>newSignalled.
Explanation from Ben Coman:
Semaphore>>forMutualExclusion
*encourages* people to believe
semaphores
can be used *on*their*own* for mutual exclusion, when
they
*shouldn't*.��
You *must* add ownership.�� If the mutual exclusion
object
doesn���t have ownership then, irrelevant of what it is
called,
it is
not a mutex!!! [1].
And more:��
With an
implementation like..
�� ��
Semaphore>>forMutualExclusion
�� �� ��
�� ^self new signal
we don't
gain a lot, and its a misleading convenience method
since its
doesn't
provide the proper facility for mutual exclusion (and I
do
conflate
mutual exclusion == mutex).�� ��Indeed, "Semaphore
forMutualExclusion
+ roll your ownership management + problems since
you
weren't aware you needed to roll your own ownership
management" is
not
more convenient than "Mutex new"
If you want
to keep a convenience method for a pre signalled
Semaphore,
then we could provide something like�� "Semaphore
newSignalled"
��
It is also explain why we should deprecate
Semaphore>>critical: and use Mutex>>critical:
instead. That's second change.
So we want to move 4 Semaphore methods to Mutex:
- critical: mutuallyExcludedBlock
It will relies on new Semaphore method waitIfInterrupted:
which block is executed when waiting process terminated at
point where lock was not acquired. Slice for this already in
inbox.
- critical: mutuallyExcludedBlock ifCurtailed:
terminationBlock
- critical: mutuallyExcludedBlock ifError: errorBlock
Semantic of this method is like BlockCosure>>ifError:.
It culls error properties to handler block. It will be changed
to cull only error instance.
It will touch WeakArray and WeakRegistry. Now they doing
this:
ifError:[:msg :rcvr| rcvr error: msg].
No special logic inside handler. So we will just use #critical:
message.
- critical: mutuallyExcludedBlock ifLocked:
alternativeBlock
It purpose looks like "enter critical section without
waiting otherwise alternativeBlock". But implementation not
shows that waiting can not be happens:
critical: mutuallyExcludedBlock ifLocked:
alternativeBlock
[��^alternativeBlock
value ].
^self
critical: mutuallyExcludedBlock
When critical message is sent but it method not started
interrupt can happen and other process can lock this
semaphore. And when process will be resumed it will be
blocked.
So implementation is not correct to me. It should be
changed somehow.
Welcome for suggestions