+capped-queue is also general. Move to zuse and add tests.

This commit is contained in:
Elliot Glaysher 2018-08-27 15:25:33 -07:00
parent 7f623772ac
commit e1ee2b211e
4 changed files with 189 additions and 67 deletions

View File

@ -185,69 +185,6 @@
care-paths=(set [care=care:clay =path])
== == == ==
--
::
|%
:: +capped-queue: a +qeu with a maximum number of entries
::
++ capped-queue
|* item-type=mold
$: queue=(qeu item-type)
size=@ud
max-size=_64
==
--
|%
:: +to-capped-queue: interface door for +capped-queue
::
++ to-capped-queue
|* item-type=mold
|_ queue=(capped-queue item-type)
:: +put: enqueue :item, possibly popping and producing an old item
::
++ put
|= item=item-type
^- [(unit item-type) _queue]
:: are we already at max capacity?
::
?. =(size.queue max-size.queue)
:: we're below max capacity, so push and increment size
::
=. queue.queue (~(put to queue.queue) item)
=. size.queue +(size.queue)
::
[~ queue]
:: we're at max capacity, so pop before pushing; size is unchanged
::
=^ oldest queue.queue ~(get to queue.queue)
=. queue.queue (~(put to queue.queue) item)
::
[`oldest queue]
:: +get: pop an item off the queue, adjusting size
::
++ get
^- [item-type _queue]
::
=. size.queue (dec size.queue)
=^ oldest queue.queue ~(get to queue.queue)
::
[oldest queue]
:: change the :max-size of the queue, popping items if necessary
::
++ resize
=| pops=(list item-type)
|= new-max=@ud
^+ [pops queue]
:: we're not overfull, so no need to pop off more items
::
?: (gte new-max size.queue)
[(flop pops) queue(max-size new-max)]
:: we're above capacity; pop an item off and recurse
::
=^ oldest queue get
::
$(pops [oldest pops])
--
--
|%
:: +axle: overall ford state
::

View File

@ -40,6 +40,14 @@
:: miscellaneous systems types
::+|
++ ares (unit {p/term q/(list tank)}) :: possible error
:: +capped-queue: a +qeu with a maximum number of entries
::
++ capped-queue
|* item-type=mold
$: queue=(qeu item-type)
size=@ud
max-size=_64
==
:: +clock: polymorphic cache type for use with the clock replacement algorithm
::
:: The +by-clock core wraps interface arms for manipulating a mapping from
@ -5540,6 +5548,59 @@
size 0
==
--
:: +to-capped-queue: interface door for +capped-queue
::
:: Provides a queue of a limited size where pushing additional items will
:: force pop the items at the front of the queue.
::
++ to-capped-queue
|* item-type=mold
|_ queue=(capped-queue item-type)
:: +put: enqueue :item, possibly popping and producing an old item
::
++ put
|= item=item-type
^- [(unit item-type) _queue]
:: are we already at max capacity?
::
?. =(size.queue max-size.queue)
:: we're below max capacity, so push and increment size
::
=. queue.queue (~(put to queue.queue) item)
=. size.queue +(size.queue)
::
[~ queue]
:: we're at max capacity, so pop before pushing; size is unchanged
::
=^ oldest queue.queue ~(get to queue.queue)
=. queue.queue (~(put to queue.queue) item)
::
[`oldest queue]
:: +get: pop an item off the queue, adjusting size
::
++ get
^- [item-type _queue]
::
=. size.queue (dec size.queue)
=^ oldest queue.queue ~(get to queue.queue)
::
[oldest queue]
:: change the :max-size of the queue, popping items if necessary
::
++ resize
=| pops=(list item-type)
|= new-max=@ud
^+ [pops queue]
:: we're not overfull, so no need to pop off more items
::
?: (gte new-max size.queue)
[(flop pops) queue(max-size new-max)]
:: we're above capacity; pop an item off and recurse
::
=^ oldest queue get
::
$(pops [oldest pops])
--
--
:: ::
:::: ++userlib :: (2u) non-vane utils

View File

@ -0,0 +1,128 @@
/+ tester
::
=, contain
::
|_ _tester:tester
++ test-basic-capped-queue
::
=| q=(capped-queue @u)
=. max-size.q 3
:: specialize type
::
=+ to-capped-queue=(to-capped-queue @u)
:: push a single element
::
=^ maybe1 q (~(put to-capped-queue q) 5)
::
=/ results1
%- expect-eq !>
:- ~
maybe1
=/ results2
%- expect-eq !>
:- 1
size.q
=/ results3
%- expect-eq !>
:- [~ 5]
~(top to queue.q)
:: remove the single element
::
=^ maybe2 q ~(get to-capped-queue q)
::
=/ results4
%- expect-eq !>
:- 5
maybe2
=/ results5
%- expect-eq !>
:- 0
size.q
::
;: weld
results1
results2
results3
results4
results5
==
::
++ test-put-returns-evicted-value
::
=| q=(capped-queue @u)
=. max-size.q 2
:: specialize type
::
=+ to-capped-queue=(to-capped-queue @u)
:: push enough values to evict one
::
=^ maybe1 q (~(put to-capped-queue q) 5)
=/ results1
%- expect-eq !>
:- ~
maybe1
=/ results2
%- expect-eq !>
:- 1
size.q
::
=^ maybe2 q (~(put to-capped-queue q) 6)
=/ results3
%- expect-eq !>
:- ~
maybe2
=/ results4
%- expect-eq !>
:- 2
size.q
::
=^ maybe3 q (~(put to-capped-queue q) 7)
=/ results5
%- expect-eq !>
:- [~ 5]
maybe3
=/ results6
%- expect-eq !>
:- 2
size.q
::
;: weld
results1
results2
results3
results4
results5
results6
==
::
++ test-resize-evicts-on-shrink
::
=| q=(capped-queue @u)
=. max-size.q 5
:: specialize type
::
=+ to-capped-queue=(to-capped-queue @u)
::
=^ maybe1 q (~(put to-capped-queue q) 1)
=^ maybe2 q (~(put to-capped-queue q) 2)
=^ maybe3 q (~(put to-capped-queue q) 3)
=^ maybe4 q (~(put to-capped-queue q) 4)
=^ maybe5 q (~(put to-capped-queue q) 5)
:: resize the size to 3; this should pop two items
::
=^ pops q (~(resize to-capped-queue q) 3)
::
=/ results1
%- expect-eq !>
:- [1 2 ~]
pops
=/ results2
%- expect-eq !>
:- 3
size.q
::
;: weld
results1
results2
==
--

View File

@ -116,10 +116,6 @@
%- expect-eq !>
:- 1
~(wyt by lookup.c)
::
%- expect-eq !>
:- 1
~(dep to queue.c)
==
::
++ test-clock-resized-to-zero