critical: aBlock[signalRequired := true.semaphore waitIfInterrupted: [signalRequired := false].^aBlock value] ensure: [signalRequired ifTrue: [semaphore signal]]
I publish slice with MutexTest. So future changes around all this will be verified by CI2016-01-06 14:32 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com>:Ok. I wrote MutextTests which show problems. See in attachment.��Attached Mutex.st contains fix which suggest Ben for his scenario. But it broke other scenario.��Mutex>>critical: aBlock"Evaluate aBlock protected by the receiver."| activeProcess signalRequired blockValue |activeProcess := Processor activeProcess.activeProcess == owner ifTrue:[^aBlock value].signalRequired := false.[signalRequired := true.semaphore wait.owner:= activeProcess.blockValue := aBlock value] ensure: [signalRequired & (owner == activeProcess) ifTrue: [owner := nil. semaphore signal]].^blockValueMy idea of ifCurtailed: usage not helps too. But if you change MutexTest to use Semaphore instead of Mutex then all tests will be green.2016-01-06 13:38 GMT+01:00 Henrik Johansen <henrik.s.johansen@veloxit.no>:If you run it, and are confused '2 start' never shows up in transcript, I intended the start messages to be outside critical blocks, sorry for old copypasta.Cheers,HenryOn 06 Jan 2016, at 1:29 , Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
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]].
^blockValueAh, 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