On Wed, Jan 6, 2016 at 12:30 AM, Henrik Johansen <henrik.s.johansen@veloxit.no> wrote:
On 05 Jan 2016, at 5:10 , Denis Kudriashov <dionisiydk@gmail.com> wrote:
2016-01-05 16:54 GMT+01:00 Denis Kudriashov <dionisiydk@gmail.com>:
2016-01-05 16:06 GMT+01:00 Ben Coman <btc@openinworld.com>:
This is really strange! Why does the copied class Semaphore2 behave differently to the original class Semaphore? This was in build 50510.
It is so frustrating. I add tests for your cases which is red now. And one for Semaphore (inside ReadWriteLockTests) which is green
It is really crazy. I just try two experiments: 1) I move semaphore critical: logic to Mutex. Our test with mutex become red. 2) I copy Semaphore>>critical: to #critical2:. And with it Semaphore test become red.
After Semaphore to Semaphore2 and running my test case above showing its bad terminate behaviour without the special handling in Process>>terminate, I then copied Mutex to Mutex2 and made the following mod... Mutex2>>initiialize super initialize. semaphore := Semaphore2 forMutualExclusion. such that my test case with lock := Mutex2 new. also showed the bad terminate behaviour. But then copying Mutex2 to Mutex3 with the following mod to replace the call to Semaphore>>critical:... Mutex3>>critical: aBlock "Evaluate aBlock protected by the receiver." | activeProcess ensureRelease blockResult| activeProcess := Processor activeProcess. activeProcess == owner ifTrue:[^aBlock value]. ensureRelease := false. blockResult := [ ensureRelease := true. semaphore wait. owner := activeProcess. aBlock value ] ensure: [ (ensureRelease and: [ activeProcess == owner ]) ifTrue: [ owner := nil. semaphore signal ] ]. ^blockResult and my test case with lock := Mutex3 new. works fine . So again I push that Semaphore>critical: is *bad*.
So somebody definitely know about #critical: selector and it receiver
#critical: is mutual exclusion, thus a Mutex, not a Semaphore.
Yes, check Process >> #terminate, there's special code for skipping a context if the suspended process was waiting for Semaphore.
Well spotted.
The way I see it, the purpose of the caught variable in Semaphore is to not execute the ensure: if the process was suspended (and then terminated)*in* the ensure: method, before block ever executes and one starts waiting on the semaphore.
If one has made it to the wait call, caught is already true, and the ensure block would be executed on termination unwind.. That part is, as I said above, handled directly in Process >> #terminate (near the bottom) AFAICT, both parts would be need to be reflected for Monitor >> #critical: to work correctly under termination. At which point, it would seem to me a better idea (if possible) if the terminated context was culled into the ensure block, instead of muddying up Process >> #terminate further, one could then write a few ugly, but localized: ensure: [:unwoundContext | (caught and: [unwoundContext isWaitContext notl]) ifTrue: [sem signal]] instead of having to keep adding special case handling to Process >> #terminate.
Cheers, Henry
Simply, if we eliminate Semaphore>>critical: then of course no special processing is required in Process>>terminate. I suggest that after a bit of review and testing, all we'll need is Mutex3>>critical: described above. cheers -ben