Group Group Group Group Group Group Group Group Group

Bug in RingBuffer.swift

#1

In the CustomStringConvertible extension to RingBuffer, there is a bug in the description var. The line:

var index = readIndex

should be:

var index = readIndex % array.count

Otherwise, when readPointer and writePointer are greater than the size of the array (as they will be after adding/removing multiple items), index will start out being greater than writeIndex % array.count, and the loop is infinite.

Below is some playground code that will crash the current implementation.

var queue = QueueRingBuffer<String>(count: 5)
queue.enqueue("Ray")
queue.enqueue("Brian")
queue.enqueue("Eric")
queue
queue.dequeue()
queue
queue.peek

queue.enqueue("1")
queue
queue.enqueue("2")
queue
queue.dequeue()
queue.dequeue()
queue.dequeue()
queue.enqueue("3")
queue.enqueue("4")
queue.enqueue("5")
queue
queue.dequeue()
queue.dequeue()
queue.dequeue()
queue.enqueue("6")
queue.enqueue("7")
queue.enqueue("8")
queue
#2

Also, the implementation of “description” (with my change above) doesn’t work if the ring buffer is full (prints empty brackets). Try this instead–I think it’s a cleaner implementation:

public var description: String {
    var result = "["
    for index in readIndex..<writeIndex {
        if let value = array[index % array.count] {
            result += "\(value) "
        }
    }
    result += "]"
    return result
}
#3

@jomoka Can you please help with this when you get a chance? Thank you - much appreciated! :]

1 Like
#4

@jtc thanks a lot, great catch!! We will make this correction in the final release!

#5

This is almost there. It actually will have a problem when the buffer is full (it won’t print anything). Better than crashing though ;]. Anyway, the code that will be in the next. spin coming soon is:

extension RingBuffer: CustomStringConvertible {
    public var description: String {
        let values = (0..<availableSpaceForReading).map {
            String(describing: array[($0 + readIndex) % array.count]!)
        }
        return "[" + values.joined(separator: ", ") + "]"
    }
}
#7

I believe the code I proposed does work when the buffer is full. Could you show me some playground code that breaks it? Maybe I’m missing something here.

readIndex and writeIndex do not wrap back to 0 as they are incremented, so writeIndex will always be bigger than readIndex whenever the buffer is full, and the “for” loop in my code should print the correct number of things…

Thanks!