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 excessSignals == 0 ifTrue: [ ^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