mirror of
https://github.com/urbit/shrub.git
synced 2025-01-03 10:02:32 +03:00
+capped-queue is also general. Move to zuse and add tests.
This commit is contained in:
parent
7f623772ac
commit
e1ee2b211e
@ -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
|
||||
::
|
||||
|
@ -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
|
||||
|
128
tests/sys/zuse/contain/capped-queue.hoon
Normal file
128
tests/sys/zuse/contain/capped-queue.hoon
Normal 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
|
||||
==
|
||||
--
|
@ -116,10 +116,6 @@
|
||||
%- expect-eq !>
|
||||
:- 1
|
||||
~(wyt by lookup.c)
|
||||
::
|
||||
%- expect-eq !>
|
||||
:- 1
|
||||
~(dep to queue.c)
|
||||
==
|
||||
::
|
||||
++ test-clock-resized-to-zero
|
||||
|
Loading…
Reference in New Issue
Block a user