On 05 Jan 2016, at 7:52 , Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:


On 05 Jan 2016, at 7:24 , Denis Kudriashov <dionisiydk@gmail.com> wrote:


2016-01-05 18:49 GMT+01:00 Henrik Johansen <henrik.s.johansen@veloxit.no>:
ifCurtailed: only unwinds if an error/termination occured, so that would mean not signalling the semaphore when everything goes as planned, and we leave the critical section...

I not suppose to replace #ensure: with #ifCurtailed:. I think about:

signalRequired := false.
[
[signalRequired := true.
self wait] ifCurtailed: [signalRequired := false].
blockValue := mutuallyExcludedBlock value
] ensure: [signalRequired ifTrue: [self signal]].
^blockValue


Ah, that makes more sense, yes, much simpler than what I wrote!
AFAICT, it should work too ;)

After thinking a bit more, it suffers from a similar edge case where the semaphore has been signaled, but process is terminated before it's had a chance to run, after changing to ifCurtailed and cleaning #terminate:

"This runs on UI thread, pri 40"
waiter := Semaphore new.
waiter2 := Semaphore new.
lock := Semaphore forMutualExclusion.

proc := [lock critical: [ Transcript crShow: '1 start'.
waiter wait. 
Transcript crShow: '1 done'.]] newProcess.
proc priority: 70.
proc resume.

proc2 := [lock critical: [ Transcript crShow: '2 start'.
waiter2 wait.
Transcript crShow: '2 done'. ]] newProcess.
proc2 priority: 15.
proc2 resume.

"Yield for proc2 so it gets to waiting on lock"
1 second wait.
"Signal waiter and yield, causing proc1 to run, and release the lock. lock will then remove proc2 from waiting list"
waiter signal.
Processor yield.
"We have a higher pri than proc2, and will resume execution here before proc2 has chance to run"
proc2 terminate.
"proc2 has been curtailed before running, thus ifCurtailed: guard is still on stack and will be run as part of termination."
(lock instVarNamed: 'excessSignals') 0 "Should be 1"

Cheers,
Henry