Semaphore and Mutex changes summary

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

Semaphore and Mutex changes summary

Denis Kudriashov
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


Reply | Threaded
Open this post in threaded view
|

Re: Semaphore and Mutex changes summary

stepharo
thanks for the summary.
I think that this is important to update the class comments with the comment of ben.
I read several blogs of mutex vs semaphore and this is nice to get this cleared out.

Stef

Le 7/1/16 14:05, Denis Kudriashov a écrit :
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



Reply | Threaded
Open this post in threaded view
|

Re: Semaphore and Mutex changes summary

Ben Coman
I found the blogs by real-time OS guys (RTOS) have more interesting
opinions on the finer points.  They are the ones who are down in the
trenches.
cheers -ben

On Sat, Jan 9, 2016 at 4:17 AM, stepharo <[hidden email]> wrote:

> thanks for the summary.
> I think that this is important to update the class comments with the comment
> of ben.
> I read several blogs of mutex vs semaphore and this is nice to get this
> cleared out.
>
> Stef
>
> Le 7/1/16 14:05, Denis Kudriashov a écrit :
>
> 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
>
>
>

Reply | Threaded
Open this post in threaded view
|

Re: Semaphore and Mutex changes summary

stepharo


Le 9/1/16 03:04, Ben Coman a écrit :
> I found the blogs by real-time OS guys (RTOS) have more interesting
> opinions on the finer points.  They are the ones who are down in the
> trenches.

Yes I read them too even if I got lost probably :)

> cheers -ben
>
> On Sat, Jan 9, 2016 at 4:17 AM, stepharo <[hidden email]> wrote:
>> thanks for the summary.
>> I think that this is important to update the class comments with the comment
>> of ben.
>> I read several blogs of mutex vs semaphore and this is nice to get this
>> cleared out.
>>
>> Stef
>>
>> Le 7/1/16 14:05, Denis Kudriashov a écrit :
>>
>> 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
>>
>>
>>
>


Reply | Threaded
Open this post in threaded view
|

Re: Semaphore and Mutex changes summary

Denis Kudriashov
In reply to this post by Denis Kudriashov

2016-01-07 14:05 GMT+01:00 Denis Kudriashov <[hidden email]>:
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.

It was wrong idea. I stop slice for the better solution. I will post about it later