Character Queues

The file Common\Cqueues.fth provides circular character (byte) queues. If the equate TASKING? is non-zero, the blocking routines will use PAUSE. Interrupts are disabled for the queue empty/full checks.

Queue data structure

struct /cqueue  \ -- size ; character queue structure in idata, buffer in udata
Circular queue data structure.

  int >qhead            \ Offset of head, where characters are taken from
  int >qtail            \ Offset of tail, where characters are put
  int >qchars           \ Number of characters in the queue
  int >qmask            \ Mask to apply to pointers
  ptr >qbuffer          \ Base address of character buffer
end-struct

: cqueue:       \ size -- ; -- cqueue ; size CQUEUE: <name>
An interpreter definition to build a character queue of the specified size. The queue data structure is built in the current IDATA space, and the buffer itself is in the current UDATA space. Executing <name> returns the address of the queue data structure. N.B. The size of a queue must be a power of two, e.g. 32, 64 ...

: init-cqueue   \ cqueue -- ; initialise queue
Initialise the specified queue created by CQUEUE:.

: init-hcqueue  \ size cqueue -- ; SFP002
Initialise the specified queue created by ALLOCATE. When a queue is allocated from the heap by a phrase of the form /CQUEUE <size> + ALLOCATE, this word must be used.

Queue primitives

: (>cqueue)     \ char cqueue -- ; put character on cqueue
Put char into the queue with no checks.

: (cqueue>)     \ cqueue -- char ; get next character from queue
Get the next character from the queue with no checks.

: (cqfull?)     \ queue -- flag ; TRUE if queue full
Return true if the queue is full. No interrupt protection is provided.

: cqfull?       \ queue -- flag ; TRUE if queue full
Return true if the queue is full. Interrupt protection is provided.

: cqchars       \ queue -- n
Return the number of characters in the queue.

: cqempty?      \ queue -- flag ; TRUE if queue empty
Return true if the queue is empty.

: cqnotempty?   \ queue -- flag ; TRUE if queue not empty
Return true if the queue is not empty, i.e. if it contains any characters.

: cqRoom        \ queue -- u
Return the number of free bytes in the queue.

: cqroom?       \ +n queue -- flag
Return true if there is enough room in the queue for +n more characters.

: >cqueue       \ char cqueue -- ; spins if full
Put a character into the queue. If the queue is full, the system waits (blocks) until there is enough space.

: cqueue>       \ queue -- char ; spins while queue empty
Remove the next character, waiting if the queue is empty.

Extended queue operations

When queues are filled and emptied in blocks rather than character by character, faster operation can be achieved using these words. You may see additional benefit using the fast version of CMOVE.

The extended operations are compiled if the equate extCQ? is set non-zero before Cqueues.fth is compiled.

0 equ extCQ?    \ -- flag
If set non-zero here or before Cqueues.fth is compiled, the extended wordset below will be compiled.

Primitives

: /tailw                \ queue -- len
Number of bytes from the tail to the end.

: /gapw         \ queue -- len
Number of bytes from the tail to the head, assuming no wrap.

: +tail         \ n queue --
Add n characters to the tail pointer and count.

: $>cq          \ caddr len n queue -- caddr' len' queue
Copy n bytes of the the source block into the buffer.

: $>tail        \ caddr len queue -- caddr' len' queue
Add block in space between tail and end

: $>gap         \ caddr len queue -- caddr' len' queue
Add block in space between tail and head.

: /headr        \ queue -- len
Number of bytes from the head to the end.

: /gapr         \ queue -- len
Number of bytes from the head to the tail, assuming no wrap.

: -head         \ n queue --
Remove n characters from the head pointer and count.

: cq>$          \ caddr len n queue -- caddr' len' queue
Copy n bytes from the queue into the buffer caddr/len.

: head>$        \ caddr len queue -- caddr' len' queue
Copy queue block in space between head and end

: gap>$         \ caddr len queue -- caddr' len' queue
Add block in space between head and tail.

User words

: cqWrite       \ caddr len queue --
Write the given string to the queue. This word blocks until the operation is complete.

: cqStuff       \ caddr len queue -- n
Write as much data from the given string to the queue as there is room for. Return the number of bytes written.

: cqRead        \ caddr len queue --
Read the given string from the queue. This word blocks until the operation is complete.

: cqExtract     \ caddr len queue -- n
Read data from the queue to the buffer. The amount read is limited by the size of the buffer and the number of bytes in the queue. The number of bytes read is returned.