[Q] SharedQueue Bug or Feature?

Boris Gaertner Boris.Gaertner at gmx.net
Fri Aug 5 04:28:54 UTC 2005


 "Sungijn Chun" <chunsj at embian.com> wrote:
> Hi,
> 
> I'm trying to create producer/consumer example using SharedQueue class.
> But when I want to fill queue(which is a instance of SharedQueue) with 2
> different processes like this:
> 
> [1 to: 20 do: [ :i |
>  | j |
>  j _ queue nextPut: i.
>  Transcript show: 'Push: ', (i asString), '(', (j asString), ')'; cr
> ]] fork.
> [21 to: 40 do: [ :i |
>  | j |
>  j _ queue nextPut: i.
>  Transcript show: 'Push: ', (i asString), '(', (j asString), ')'; cr
> ]] fork.
> 
> the queue does not contain entire 40 elements, it just drops some of them
>  randomly. I think SharedQueue can handle this kind of situation but I 
> cannot
> figure out what is my problem. I'm using 3.8 image in windows and linux.
> 
> Thanks in advance. 
> 

I do not think that there is something wrong with
SharedQueue, but I am really not comfortable with
your example.

Please try this and compare the results:

  | queue  |
 queue := SharedQueue new.
[1 to: 20 do: [ :i1 |
 | j1 |
 j1 _ queue nextPut: i1.
 Transcript show: 'Push: ', (i1 asString), '(', (j1 asString), ')'; cr
]] fork.
[21 to: 40 do: [ :i2 |
 | j2 |
 j2 _ queue nextPut: i2.
 Transcript show: 'Push: ', (i2 asString), '(', (j2 asString), ')'; cr
]] fork.
queue inspect

You see that I changed the names of the block-local variables
 - they are now distinct.  I think this is an issue. Keep in
mind that we still do not have real blocks: The local variables
of a block are not really local; the compiler moves them into
the method that provides the evaluation environment.
In your example, your processes share these
variables:  queue, i, j

In my example, the processes share the varialbe  queue,
but have their own counters and auxiliary variables  i1, j1
resp.  i2, j2.

To avoid unwanted name clashes, it is possible to
place every block into a method. This is what I 
normally do.

When you define this method in a suitably defined class:

createBlockWith: start with: stop with: queue
  ^  [start to: stop do: [ :i |
        | j |
        j _ queue nextPut: i.
        Transcript show: 'Push: ', (i asString), '(', (j asString), ')'; cr
       ]
].

you can write:

  | queue |
 queue := SharedQueue new.
 (self createBlockWith: 1 with: 20 with: queue) fork.
 (self createBlockWith: 21 with: 40 with: queue) fork.
queue inspect

This creates two blocks with distinct instances
of variables i, j.

It would be interesting to try your example with the
optional block closure package loaded into your image,
but just now I do not have the time to do that - I have to
go to work.

  
Greetings, Boris



More information about the Squeak-dev mailing list