#FEATURE by cg
authorClaus Gittinger <cg@exept.de>
Wed, 07 Sep 2016 15:25:13 +0200
changeset 4064 24ce8feaa923
parent 4063 4494f18b967d
child 4065 9eb6ea6224d9
#FEATURE by cg class: Queue added: #capacity: comment/format in:6 methods
Queue.st
--- 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
 !