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 <mailto:dionisiydk@gmail.com>> wrote:
2016-01-05 18:49 GMT+01:00 Henrik Johansen <henrik.s.johansen@veloxit.no <mailto: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