Currently i replacing all calls which affect the scheduling to
redirecting them to Processor, i.e. instead: self primitiveDoSomething do: Processor doSomethingWith: self. This is to ensure, that no code, in rest of classes , except ProcessorScheduler deals with scheduling directly. If i change the Semaphore>>wait method in that way, then it breaks the trick which sitting in #terminate method : "Figure out if we are terminating the process while waiting in Semaphore>>critical: In this case, pop the suspendedContext so that we leave the ensure: block inside Semaphore>>critical: without signaling the semaphore." (inSema == true and:[ suspendedContext method == (Semaphore compiledMethodAt: #critical:)]) ifTrue:[ suspendedContext := suspendedContext home. ]. What you think is following alternative implementation: critical: mutuallyExcludedBlock | blockValue caught | caught := false. [ caught := true. [self wait.] ifCurtailed: [ caught:=false ]. blockValue := mutuallyExcludedBlock value ] ensure: [caught ifTrue: [self signal]]. ^blockValue avoids the need in having tricks in #terminate? -- Best regards, Igor Stasenko AKA sig. |
2009/4/30 Igor Stasenko <[hidden email]>:
> Currently i replacing all calls which affect the scheduling to > redirecting them to Processor, i.e. instead: > self primitiveDoSomething > > do: > Processor doSomethingWith: self. > > This is to ensure, that no code, in rest of classes , except > ProcessorScheduler deals with scheduling directly. > > If i change the Semaphore>>wait method in that way, then it breaks the > trick which sitting in #terminate method : > > "Figure out if we are terminating the process while waiting in > Semaphore>>critical: > In this case, pop the suspendedContext so that we leave the ensure: > block inside > Semaphore>>critical: without signaling the semaphore." > (inSema == true and:[ > suspendedContext method == (Semaphore compiledMethodAt: > #critical:)]) ifTrue:[ > suspendedContext := suspendedContext home. > ]. > > > What you think is following alternative implementation: > > critical: mutuallyExcludedBlock > | blockValue caught | > caught := false. > [ > caught := true. > [self wait.] ifCurtailed: [ caught:=false ]. > blockValue := mutuallyExcludedBlock value > ] ensure: [caught ifTrue: [self signal]]. > ^blockValue > > avoids the need in having tricks in #terminate? > the test code: | result | result := 0. [ [ result := 5. [Processor terminateActive] ifCurtailed: [ result := 10 ]. ] ensure: [ result := 1 -> result ]. ] forkAt: Processor highestPriority. result returns result == (1->10) and: | result sema | sema := Semaphore new. result := 0. ([ [ result := 5. [sema wait] ifCurtailed: [ result := 10 ]. ] ensure: [ result := 1 -> result ]. ] forkAt: Processor highestPriority) terminate. result returns result == (1->10) as well. > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
In reply to this post by Igor Stasenko
Igor Stasenko wrote:
> What you think is following alternative implementation: > > critical: mutuallyExcludedBlock > | blockValue caught | > caught := false. > [ > caught := true. > [self wait.] ifCurtailed: [ caught:=false ]. > blockValue := mutuallyExcludedBlock value > ] ensure: [caught ifTrue: [self signal]]. > ^blockValue > > avoids the need in having tricks in #terminate? It doesn't. For example: sema := Semaphore forMutualExclusion. p := [sema critical:[]] forkAt: Processor activePriority - 1. sema critical:[( Delay forMilliseconds: 100) wait]. p terminate. self assert: sema isSignaled. Cheers, - Andreas |
2009/4/30 Andreas Raab <[hidden email]>:
> Igor Stasenko wrote: >> >> What you think is following alternative implementation: >> >> critical: mutuallyExcludedBlock >> | blockValue caught | >> caught := false. >> [ >> caught := true. >> [self wait.] ifCurtailed: [ caught:=false ]. >> blockValue := mutuallyExcludedBlock value >> ] ensure: [caught ifTrue: [self signal]]. >> ^blockValue >> >> avoids the need in having tricks in #terminate? > > It doesn't. For example: > > sema := Semaphore forMutualExclusion. > p := [sema critical:[]] forkAt: Processor activePriority - 1. > sema critical:[( Delay forMilliseconds: 100) wait]. > p terminate. > self assert: sema isSignaled. > Ok, any ideas how to ensure expected behavior without poking the context stack? Because in new scheduler, a #wait implemented differently. > Cheers, > - Andreas > > -- Best regards, Igor Stasenko AKA sig. |
With implementation of TerminateProcess exception, i now solved this issue.
sema := Semaphore forMutualExclusion. p := [sema testCritical:[]] forkAt: Processor activePriority - 1. sema testCritical:[( Delay forMilliseconds: 100) wait]. p terminate. self assert: sema isSignaled. now works w/o failure in new scheduler. A code for critical section now looks like: critical: mutuallyExcludedBlock "Evaluate mutuallyExcludedBlock only if the receiver is not currently in the process of running the critical: message. If the receiver is, evaluate mutuallyExcludedBlock after the other critical: message is finished." | blockValue caught | caught := false. [ caught := true. [self wait] on: TerminateProcess do: [:ex | caught := ex abandonedSemaphore ~~ self ]. blockValue := mutuallyExcludedBlock value ] ensure: [caught ifTrue: [self signal]]. ^blockValue 2009/4/30 Igor Stasenko <[hidden email]>: > 2009/4/30 Andreas Raab <[hidden email]>: >> Igor Stasenko wrote: >>> >>> What you think is following alternative implementation: >>> >>> critical: mutuallyExcludedBlock >>> | blockValue caught | >>> caught := false. >>> [ >>> caught := true. >>> [self wait.] ifCurtailed: [ caught:=false ]. >>> blockValue := mutuallyExcludedBlock value >>> ] ensure: [caught ifTrue: [self signal]]. >>> ^blockValue >>> >>> avoids the need in having tricks in #terminate? >> >> It doesn't. For example: >> >> sema := Semaphore forMutualExclusion. >> p := [sema critical:[]] forkAt: Processor activePriority - 1. >> sema critical:[( Delay forMilliseconds: 100) wait]. >> p terminate. >> self assert: sema isSignaled. >> > > Ok, any ideas how to ensure expected behavior without poking the context stack? > Because in new scheduler, a #wait implemented differently. > >> Cheers, >> - Andreas >> >> > > > > -- > Best regards, > Igor Stasenko AKA sig. > -- Best regards, Igor Stasenko AKA sig. |
Free forum by Nabble | Edit this page |