module jin.go.cursor;

import core.atomic;
alias acquire = MemoryOrder.acq;
alias release = MemoryOrder.rel;

import jin.go.mem;

/// Atomic buffer cursor.
align(Line) struct Cursor
{
    /// Offset in buffer.
    align(Line) private shared size_t _offset;

    /// Offset in buffer.
    size_t offset() const
    {
        return this._offset.atomicLoad!acquire;
    }

    /// Offset in buffer. Can't be changed when finalized.
    void offset(size_t next)
    {
        assert(this._finalized == 0, "Change offset of finalized cursor");
        this._offset.atomicStore!release(next);
    }

    /// Finalized cursor shall never change offset.
    align(Line) private shared ptrdiff_t _finalized;

    /// Finalized cursor shall never change offset.
    ptrdiff_t finalized() const
    {
        return this._finalized.atomicLoad!acquire;
    }

    /// Finalize cursor to prevent offset changes.
    void finalize()
    {
        this._finalized.atomicStore!release(ptrdiff_t(-1));
    }
}