The following is possible in my forth
( ) words are quotations or anonymous definitions, not comments.
This is inspired from Ron's 8th. :)
I used a wordlist to make the fields names and some other internal
words "local".
\ ==================================================
raimond....@gmail.com
\ Fifos (Queues)
\ v1.23 12jan2016
\ =============================================================================
\ usage:
\ 64 cfifo:new G G is a 64 byte fifo
\ 64 hfifo:new G G is a 64 x 16bit fifo (128 bytes buffer)
\ 64 fifo:new G G is a 64 cells fifo (256 bytes buffer for 32bit cell)
\ then we have the following words:
\ G -- a address of the whole fifo structure (good for dump)
\ G:reset -- reset the G fifo
\ G:empty? -- f is the G fifo empty?
\ G:full? -- f is the G fifo full?
\ G:put x -- f put x on G fifo, return T if succes, F if fifo full
\ G:get -- x f get x from G fifo, return T if succes, F if fifo empty
\ G:len -- x the number of elements in the G fifo
\ G:avail -- x the number of empty (available) slots in the G fifo
wordlist fifoW \ wordlist for internal fifo words
fifoW also \ make it available in search order
current@ \ save current on the data stack
fifoW current! \ set fifoW current
\ General fifo structure
0 w field .in \ in pointer
w field .out \ out pointer
w field .start \ start of the fifo buffer
w field .end \ end of the fifo buffer
constant fifo
\ The entire fifo data structure will consists of the above header followed
\ by the actual data buffer.
: ff:mod \ oldx ff -- newx
>r dup r@ .end @ = if drop r@ .start @ then r>drop ;
: ff:empty? \ ff -- f
dup .out @ swap .in @ = ;
: ff:full? \ ff -- f
dup .in @ over .out @ 1+ rot ff:mod = ;
: ff:reset \ ff --
dup>r .start @ dup r@ .in ! r> .out ! ;
: ff:init \ a u ff -- , u is in bytes
>r over + r@ .end ! r@ .start ! r> ff:reset ;
\ ---------------------- 8bit fifo ----------------------------
: ff:c! \ c ff -- f
dup>r .in @ dup 1+ r@ ff:mod
dup r@ .out @ = if \ full
2nip r> 2drop false exit
then
r> .in !
c! true ; \ store byte in fifo, return true
: ff:c@ \ ff -- c f
dup>r .out @ dup r@ .in @ = if r>drop false exit then \ empty
dup c@ \ fetch byte from fifo
swap 1+ r@ ff:mod r> .out ! true ;
: ff:c# \ ff -- n, used space in bytes
dup>r .in @ r@ .out @ - dup 0< if
r@ .end @ + r@ .start @ -
then
r>drop ;
: ff:c? \ ff -- n, available space in bytes
dup>r .end @ r@ .start @ - r> ff:c# - 1- ;
\ --------------------- 16bit fifo ----------------------------
: ff:h! \ h ff -- f
dup>r .in @ dup 2 + r@ ff:mod
dup r@ .out @ = if \ full
2nip r> 2drop false exit
then
r> .in !
h! true ; \ store h in fifo, return true
: ff:h@ \ ff -- h f
dup>r .out @ dup r@ .in @ = if r>drop false exit then \ empty
dup h@ \ fetch h from fifo
swap 2 + r@ ff:mod r> .out ! true ;
: ff:h# \ ff -- n, used space in bytes
dup>r .in @ r@ .out @ - dup 0< if
r@ .end @ + r@ .start @ -
then 2/
r>drop ;
: ff:h? \ ff -- n, available space in bytes
dup>r .end @ r@ .start @ - 2/ r> ff:h# - 1- ;
\ --------------------- 32bit fifo ----------------------------
: ff:! \ x ff -- f
dup>r .in @ dup cell+ r@ ff:mod
dup r@ .out @ = if \ full
2nip r> 2drop false exit
then
r> .in !
! true ; \ store in fifo, return true
: ff:@ \ ff -- x f
dup>r .out @ dup r@ .in @ = if r>drop false exit then \ empty
dup @ \ fetch from fifo
swap cell+ r@ ff:mod r> .out ! true ;
: ff:# \ ff -- n, used space in bytes
dup>r .in @ r@ .out @ - dup 0< if
r@ .end @ + r@ .start @ -
then 2/ 2/
r>drop ;
: ff:? \ ff -- n, available space in bytes
dup>r .end @ r@ .start @ - 2/ 2/ r> ff:# - 1- ;
\ ---------- defining words -----------------------------------
: fifonew \ size n <name> -- str len ptr
here @ >r \ n size R: ptr ptr points to our memory area (fifo ptr)
>r \ size R: ptr n n is cell size of the fifo
bl parse \ size str len
2dup (data) \ <name> is just as any other var
rot 1+ \ str len size+1 buffer size is one more item
r> * \ str len size R: ptr size is in bytes now
dup fifo + allot \ allocate the fifo structure + buffer
r@ fifo + \ str len size adr adr is the fifo buffer address
swap \ str len adr size size is the fifo buffer size
r@ ff:init \ str len R: ptr init the fifo
2dup s" :clear" strcat ( @ ff:reset ) (build) r@ ,
2dup s" :empty?" strcat ( @ ff:empty? ) (build) r@ ,
2dup s" :full?" strcat ( @ ff:full? ) (build) r@ ,
r> ; \ str len ptr
current! \ restore current to compile the public words
: cfifo:new \ len <name> --
c fifonew >r
2dup s" :put" strcat ( @ ff:c! ) (build) r@ ,
2dup s" :get" strcat ( @ ff:c@ ) (build) r@ ,
2dup s" :len" strcat ( @ ff:c# ) (build) r@ ,
s" :avail" strcat ( @ ff:c? ) (build) r> ,
;
: hfifo:new \ len <name> --
h fifonew >r
2dup s" :put" strcat ( @ ff:h! ) (build) r@ ,
2dup s" :get" strcat ( @ ff:h@ ) (build) r@ ,
2dup s" :len" strcat ( @ ff:h# ) (build) r@ ,
s" :avail" strcat ( @ ff:h? ) (build) r> ,
;
: fifo:new \ len <name> --
w fifonew >r
2dup s" :put" strcat ( @ ff:! ) (build) r@ ,
2dup s" :get" strcat ( @ ff:@ ) (build) r@ ,
2dup s" :len" strcat ( @ ff:# ) (build) r@ ,
s" :avail" strcat ( @ ff:? ) (build) r> ,
;
previous \ take out the fifoW from search order