Multiple processes using #nextPutAll:

Andreas Raab andreas.raab at gmx.de
Tue May 29 07:40:24 UTC 2007


Yes, that is a very clever solution. You could tidy this up a little by 
using:

Array subclass: #YieldingArray
     instanceVariableNames:''
     classVariableNames: ''
     poolDictionaries: ''
     category: 'Temp'

YieldingArray>>do: aBlock
    "Evaluate aBlock with all the arguments. Yield in the middle."
     1 to: self size do:[:i|
         aBlock value: i.
         Processor yield.
     ].

#yield will take care of things without a semaphore due to Squeak's 
process scheduling rules.

Cheers,
   - Andreas

Martin v. Löwis wrote:
>>  queue := self newQueue.
>>  writingBlock := [queue nextPutAll: (1 to: 10000)].
>>  writingBlock
>>    fork;
>>    fork;
>>    fork.
>>  Processor yield.
>>  self assert: (queue next: 10000) asArray = (1 to: 10000) asArray.
>>  self assert: (queue next: 10000) asArray = (1 to: 10000) asArray.
>>  self assert: (queue next: 10000) asArray = (1 to: 10000) asArray.
>>  self assert: queue atEnd.
>>
>>
>> I assume it's because when I fork, the work is done before the
>> following fork starts.
>>
>> Can somebody help me writing this test?
> 
> I assume that nextPutAll: relies on do: to fetch all elements of
> the collection. So you could define a BlockingCollection, which
> contains a collection, and a semaphore as instance variables.
> Then, do: would do
> 
> do: aBlock
>   collection do:[:each|
>      semaphore wait.
>      aBlock value: each.
>      semaphore signal.
>   ].
> 
> Alternatively, if it relies on at: also implement
> 
> at: index
>   | result |
>   semaphore wait.
>   result := collection at: index.
>   semaphore signal.
>   ^result.
> 
> Then, in the test, you do
> 
> sem := Semaphore new.
> writingBlock := [queue nextPutAll:
>    (BlockingCollection on: (1 to: 10000) with: sem)].
> sem signal.
> 
> HTH,
> Martin
> 
> 
> 




More information about the Squeak-dev mailing list