# Rolling stream

This unit implements a rolling stream [io/stream], that is, a static buffer with
a read and write pointer. When a pointer reaches the end of the buffer, it rolls
over to the beginning.

When both pointers are equal, the buffer is empty, when the write pointer is one
less than the read pointer, the buffer is full.

This might sound similar to [mem/scratch], but unlike it, this buffer doesn't
blissfully overwrite contents. When it's full, it refuses writing.

This buffer is designed to be fast and accomodate the needs for shoveling bytes
around when handling IRQs [doc/intr].

## Reading buffer lifetime

When reading from the buffer, you'll need a little bit of time to process that
memory range you're given before further IRQs write over it. For this reason,
the memory that a readbuf call frees isn't actually freed until the *next* call,
therefore giving the caller the time to copy it elsewhere.

This is what the "nextridx" field is for.

## Example usage

  needs mem/roll
  $100 const BUFSZ
  BUFSZ newrollingbuffer const mybuf
  "hello" mybuf puts \ works like any stream

## API

### Structures

extends Stream struct RollBuf {
  uint ridx widx nextridx bufsz ;
  [void,0] buffer ;
}

### Words

newrollingbuffer ( bufsz -- rollbuf )
  Allocates a new rolling stream of the specified size in bytes.

fastputc, ( -- fullbr )
  Compiles a fast equivalent to "putc". The runtime code has this signature:

  IN: A=rollbuf W=c  OUT: A=rollbuf CLOBBERED: W S

  The compile time word yields a branch to the case where the buffer is full.
  Example usage:

    fastputc,
      \ code handling the regular case
    else
      \ code handling the "full" error
    then
