Squeak
  links to this page:    
View this PageEdit this PageUploads to this PageHistory of this PageTop of the SwikiRecent ChangesSearch the SwikiHelp Guide
True Cooperative Threads?
Last updated at 2:28 pm UTC on 16 April 2005
While it is true that Squeak's processes are non-preemptive if they run at the same priority their behavior is somewhat out of the ordinary when they get preempted by a higher priority process. Rather than being added as the first process in the priority group (which would give you the expected behavior) the preempted process is added as the last process thereby implicitly yielding to the next process in this priority group.

There's a simple choice that has to be made when suspending Processes; add to the front of the priority queue or the back? The Blue Book specified 'back' and that's what Squeak does. VisualWorks changed to use 'front' on the grounds that it would do what you are expecting.

We could easily change Squeak (especially now we have the primitiveYield), but no one has stepped up to say that it would be a clear improvement. One way makes a process run until it completes and the other allows a sort of 'fair shake' for all the processes at a priority.



Example

aStream := WriteStream on: (String new: 200).
aSemaphore := Semaphore new.
aBlockClosure := [:argument | 0 to: 9
    do:
        [:n |
                 aStream nextPutAll: argument.
                 aStream nextPutAll: '('.
                 aStream nextPutAll: n printString.
                 aStream nextPutAll: ')'.
                 aStream nextPutAll: ' '.
                 1000 timesRepeat: [100 factorial].
                 ].
    aSemaphore signal].
aBlockClosure2 := [:argument2 | 0 to: 9
    do:
        [:n2 |
                 aStream nextPutAll: argument2.
                 aStream nextPutAll: '('.
                 aStream nextPutAll: n2 printString.
                 aStream nextPutAll: ')'.
                 aStream nextPutAll: ' '.
                 100 timesRepeat: [100 factorial].
                 ].
    aSemaphore signal].
aBlockClosure3 := [:argument3 | 0 to: 9
    do:
        [:n3 |
                 aStream nextPutAll: argument3.
                 aStream nextPutAll: '('.
                 aStream nextPutAll: n3 printString.
                 aStream nextPutAll: ')'.
                 aStream nextPutAll: ' '.
                 10 timesRepeat: [100 factorial].
                 ].
    aSemaphore signal].
aStream nextPutAll: 'Black'; nextPutAll: ' '.
[aBlockClosure value: 'Red'] fork.
[aBlockClosure2 value: 'Green'] fork.
[aBlockClosure3 value: 'Blue'] fork.
aStream nextPutAll: 'White'; nextPutAll: ' '.
3 timesRepeat: [aSemaphore wait].
aStream contents
The result is funny if you are expecting no preemption for processses at the same priority:
'Black White Red(0) Red(1) Red(2) Green(0) Green(1) Green(2) Green(3)
Green(4) Green(5) Green(6) Green(7) Green(8) Green(9) Blue(0) Blue(1)
Blue(2) Blue(3) Blue(4) Blue(5) Blue(6) Blue(7) Blue(8) Blue(9) Red(3)
Red(4) Red(5) Red(6) Red(7) Red(8) Red(9) '

(Change the 'xxx timesRepeat:' value. You can get various results).
This has been tested in Squeak 3.6 & 3.7b in Windows.


In, VW and Dolphin, one gets the expected results:
'Black White Red(0) Red(1) Red(2) Red(3) Red(4) Red(5) Red(6) Red(7)
Red(8) Red(9) Green(0) Green(1) Green(2) Green(3) Green(4) Green(5)
Green(6) Green(7) Green(8) Green(9) Blue(0) Blue(1) Blue(2) Blue(3)
Blue(4) Blue(5) Blue(6) Blue(7) Blue(8) Blue(9) '