
use mem

class PtrRing {
    data: ptr
    slots: uint
    head: uint (0)
    tail: uint (0)

    static fn new() PtrRing {
        let slots : uint = 100
        return PtrRing {
            slots: slots
            data: mem:alloc(slots * size_of(ptr))
        }
    }

    fn add(item: ptr) {
        let slots = this.slots
        let head = this.head
        @ptrv(this.data, ptr, head) = item
        let new_head = head + 1
        if new_head == slots : new_head = 0

        if new_head == this.tail {
            let new_slots = slots * 2
            this.data = mem:resize(this.data, slots * size_of(ptr), new_slots * size_of(ptr))
            this.slots = new_slots
            new_head = slots
            this.tail = 0
        }

        this.head = new_head
    }
    fn pop() ptr !empty {
        let slots = this.slots
        let tail = this.tail
        if tail == this.head : throw empty
        let new_tail = tail + 1
        if new_tail == slots : new_tail = 0
        this.tail = new_tail
        return @ptrv(this.data, ptr, tail)
    }

    fn clear() {
        this.head = 0
        this.tail = 0
    }

    fn free() {
        mem:free(this.data)
        mem:free(this)
    }
}