--- a/Queue.st Wed Sep 07 13:58:52 2016 +0200
+++ b/Queue.st Wed Sep 07 15:25:13 2016 +0200
@@ -38,19 +38,20 @@
documentation
"
- Queues provide a simple implementation of a queue,
+ Queues provide a simple implementation of a collection,
where elements are added at one end and removed at the other.
- Access protocol is somewhat like a streams protocol, i.e. access
- is by #nextPut: and #next.
+ Access protocol is somewhat like a stream's protocol,
+ i.e. access is by #nextPut: and #next.
+
The queue is created with a size argument, defining how many elements
are to be stored. It will report an error if the queue ever becomes full
- and another element is to be added. Likewise, it will report an error
- if it is empty and an element is to be removed.
+ and another element is to be added.
+ Likewise, it will report an error if it is empty and an element is to be removed.
- It is NOT safe when two processes access Queues simultaneously,
+ It is NOT safe when two processes access instances of Queue simultaneously,
since accesses to the internals are not protected against process-switches.
- See SharedQueue for a class which IS safe with processes and blocks
+ See SharedQueue for a class which IS safe w.r.t. processes and which blocks
on write when full or on read when empty.
[Implementation note:]
@@ -62,7 +63,7 @@
would require that many OC methods had to be blocked and/or redefined in
such a subclass, to care for simultaneous access.
Since queue implements a much more lightweight protocol,
- the sharedQueue implementation is much cleaner when based on a more
+ the sharedQueue implementation is much cleaner when based on this more
lightweight Queue class.
[author:]
@@ -193,7 +194,11 @@
next
"return the next value in the queue;
- Return nil, if the queue is empty"
+ Return nil, if the queue is empty.
+ WARNING: this is an old behavior, which should be changed
+ to raise an error if empty.
+ It is left in here until all queue-users have been changed to
+ call nextOrNil instead, to avoid breaking existing applications."
^ self nextOrNil
!
@@ -289,6 +294,9 @@
!
removeIdentical:anElement ifAbsent:exceptionalValue
+ "remove and return a particular element from the queue;
+ Return the value from exceptionalValue if the element is not in the queue"
+
|rPos "{ Class: SmallInteger }"
wPos "{ Class: SmallInteger }"
countRemoved
@@ -395,7 +403,7 @@
!
removeLast
- "return the last value in the queue;
+ "remove and return the last value in the queue;
Return nil, if the queue is empty"
|value pos "{ Class: SmallInteger }"|
@@ -458,6 +466,49 @@
!Queue methodsFor:'initialization'!
+capacity:newSize
+ "change the capacity of the queue.
+ That is the number of slots it can hold."
+
+ |newContentsArray n1 n2|
+
+ newSize < tally ifTrue:[
+ "/ cannot make me smaller, if I hold at least this number of elements.
+ self error:'queue cannot be resized to this size while holding more elements' mayProceed:true.
+ "/ if proceeded
+ ^ self
+ ].
+ newContentsArray := Array new:newSize.
+ tally ~~ 0 ifTrue:[
+ n1 := contentsArray size - readPosition + 1.
+ n1 > tally ifTrue:[
+ newContentsArray replaceFrom:1 to:tally with:contentsArray startingAt:readPosition.
+ ] ifFalse:[
+ newContentsArray replaceFrom:1 to:n1 with:contentsArray startingAt:readPosition.
+ n2 := writePosition - 1.
+ newContentsArray replaceFrom:n1+1 to:tally with:contentsArray startingAt:1.
+ ].
+ ].
+ contentsArray := newContentsArray.
+ readPosition := 1.
+ writePosition := tally+1.
+
+ "
+ |q|
+ 1 to:10 do:[:fill |
+ 1 to:10 do:[:read |
+ Transcript show:'fill: '; show:fill; show:' read: '; showCR:read.
+ q := Queue new:10.
+ fill timesRepeat:[ q nextPut: #foo ].
+ read timesRepeat:[ q next ].
+ q capacity:12.
+ self assert:(q size == (fill-read)).
+ self assert:((Array streamContents:[:s | q do:[:e |s nextPut:e]]) = (Array new:(fill-read) withAll:#foo)).
+ ].
+ ].
+ "
+!
+
init:size
"initialize the receiver for size entries"
@@ -469,7 +520,11 @@
!Queue methodsFor:'queries'!
capacity
- "return the number of elements the queue can hold"
+ "return the number of elements the queue can hold.
+ Trying to add more will:
+ - raise an error in queue
+ - block the writer in sharedQueue
+ - lead to an automatic resize in UnlimitedSharedQueue"
^ contentsArray size
!