urbit/sys/vane/behn.hoon

198 lines
5.3 KiB
Plaintext
Raw Normal View History

:: %behn, just a timer
::
2016-11-24 07:25:07 +03:00
!? 164
::
=, behn
|= pit=vase
=> |%
+$ move [p=duct q=(wind note:able gift:able)]
+$ sign ~
::
+$ behn-state
$: timers=(list timer)
unix-duct=duct
next-wake=(unit @da)
==
::
+$ timer [date=@da =duct]
--
2016-11-24 07:25:07 +03:00
::
=| behn-state
=* state -
2018-12-06 00:41:21 +03:00
|= [our=ship now=@da eny=@uvJ ski=sley] :: current invocation
2016-11-24 07:25:07 +03:00
^?
|% :: poke+peek pattern
++ call :: handle request
2018-12-03 22:45:50 +03:00
|= $: hen=duct
type=*
wrapped-task=(hobo task:able)
2016-11-24 07:25:07 +03:00
==
^- [(list move) _..^$]
2018-12-03 22:45:50 +03:00
::
=/ =task:able
2018-12-03 22:45:50 +03:00
?. ?=(%soft -.wrapped-task)
wrapped-task
((hard task:able) p.wrapped-task)
::
|^ =^ moves state
::
?- -.task
:: %crud: error report; hand off to %dill to be printed
::
%crud
[[hen %slip %d %flog task]~ state]
::
:: %born: handle urbit restart
::
%born
:: store this duct for setting unix wakeup timers
::
=. unix-duct hen
:: process any elapsed timers and clear and reset :next-wake
::
=^ moves timers notify-clients
(set-wake(next-wake ~) moves)
::
:: %rest: cancel a timer, resetting :next-wake if needed
::
%rest
=. timers (unset-timer [p.task hen])
(set-wake ~)
::
:: %wait: set a new timer
::
%wait
:: process elapsed timers first to maintain sort order
::
=^ moves timers notify-clients
:: set the timer, then adjust :next-wake if needed
::
=. timers (set-timer [p.task hen])
(set-wake moves)
::
:: %wake: unix says wake up; notify clients and set next wakeup
::
%wake
=^ moves timers notify-clients
(set-wake(next-wake ~) moves)
::
:: %wegh: produce memory usage report for |mass
::
%wegh
:_ state :_ ~
:^ hen %give %mass
:- %behn
:- %|
:~ timers+[%& timers]
==
==
::
[moves ..^^$]
:: +set-timer: set a timer, maintaining the sort order of the :timers list
2018-11-30 23:52:32 +03:00
::
++ set-timer
|= t=timer
^+ timers
::
?~ timers
~[t]
2018-12-13 04:48:41 +03:00
:: timers at the same date form a fifo queue
::
2018-12-13 04:48:41 +03:00
?: (lth date.t date.i.timers)
[t timers]
::
[i.timers $(timers t.timers)]
:: +unset-timer: cancel a timer; if it already expired, no-op
::
++ unset-timer
|= [t=timer]
^+ timers
:: if we don't have this timer, no-op; for debugging, add a printf here
::
?~ timers
~
?: =(i.timers t)
t.timers
2016-11-24 07:25:07 +03:00
::
[i.timers $(timers t.timers)]
:: +notify-clients: wake up vanes whose timers have expired
::
:: When we return the list moves to clients, we flop them so they're in
:: the same order as they were in :timers.
::
++ notify-clients
=| moves=(list move)
|- ^+ [moves timers]
2016-11-24 07:25:07 +03:00
::
?~ timers
[(flop moves) timers]
2016-11-24 07:25:07 +03:00
::
?: (gth date.i.timers now)
[(flop moves) timers]
::
%_ $
timers t.timers
moves [[duct.i.timers %give %wake ~] moves]
2016-11-24 07:25:07 +03:00
==
:: +set-wake: set or unset a unix timer to wake us when next timer expires
::
2019-01-08 00:47:23 +03:00
:: We prepend the unix %doze event so that it is handled first. Arvo must
:: handle this first because the moves %behn emits will get handled in
:: depth-first order. If we're handling a %wake which causes a move to a
2019-01-08 00:47:23 +03:00
:: different vane and a %doze event to send to unix, Arvo needs to process
2019-01-08 00:58:08 +03:00
:: the %doze first because otherwise if the move to the other vane calls
:: back into %behn and emits a second %doze, the second %doze would be
:: handled by unix first which is incorrect.
::
++ set-wake
|= moves=(list move)
^+ [moves state]
:: if no timers, cancel existing wakeup timer or no-op
::
?~ timers
?~ next-wake
2018-12-13 09:07:05 +03:00
[moves state]
:_ state(next-wake ~)
[[unix-duct %give %doze ~] moves]
:: if :next-wake is in the past or not soon enough, reset it
::
?^ next-wake
?: &((gte date.i.timers u.next-wake) (lte now u.next-wake))
2018-12-13 09:07:05 +03:00
[moves state]
:_ state(next-wake `date.i.timers)
[[unix-duct %give %doze `date.i.timers] moves]
:: there was no unix wakeup timer; set one
::
:_ state(next-wake `date.i.timers)
[[unix-duct %give %doze `date.i.timers] moves]
--
2016-11-24 07:25:07 +03:00
::
++ load
|= old=*
2016-11-24 07:25:07 +03:00
^+ ..^$
?^ new=((soft behn-state) old)
~& %behn-load-new
..^$(state u.new)
~& %behn-load-wipe
..^$(state *behn-state)
:: +scry: view timer state
::
:: TODO: not referentially transparent w.r.t. elapsed timers,
:: which might or might not show up in the product
2016-11-24 07:25:07 +03:00
::
++ scry
|= [fur=(unit (set monk)) ren=@tas why=shop syd=desk lot=coin tyl=path]
2016-11-24 07:25:07 +03:00
^- (unit (unit cage))
::
?. ?=(%& -.why)
~
[~ ~ %tank !>(>timers<)]
2016-11-24 07:25:07 +03:00
::
++ stay state
2016-11-24 07:25:07 +03:00
++ take :: process move
|= [tea=wire hen=duct hin=(hypo sign)]
^+ [*(list move) ..^$]
~| %behn-take-not-implemented
2016-11-24 07:25:07 +03:00
!!
--