1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66
|
// Fixed size ringbuffer
RingBuffer : SequenceableCollection {
var <array, <readPos, <writePos;
*new { | size, collectionClass(Array) |
^this.newCopyArgs(collectionClass.newClear(size), 0, 0)
}
// return maximum capacity.
maxSize {
^array.size
}
// return number of readable items.
size {
^this.readable
}
// return number of readble items.
readable {
^if (readPos <= writePos)
{ writePos - readPos }
{ array.size - readPos + writePos }
}
// return number of writable items.
writable {
^array.size - this.readable - 1
}
// add value and increase writePos.
// do nothing if no items can be written.
add { | value |
if (this.writable > 0) {
array.put(writePos, value);
writePos = (writePos + 1) % array.size;
}
}
// return next readable item and increase readPos.
// return nil if no items can be read.
pop {
var result;
if (this.readable > 0) {
result = array.at(readPos);
readPos = (readPos + 1) % array.size;
};
^result
}
// add value and increase writePos by overwriting oldest readable
// item.
overwrite { | value |
var result;
if (this.writable == 0) {
result = this.pop;
};
this.add(value);
^result
}
// iterate over the currently readable items.
do { | function |
var n = this.readable, i = 0;
while { i < n } {
function.value(array.wrapAt(readPos + i), i);
i = i + 1;
}
}
}
|