 : <alarm> ( quot start interval -- alarm )
     alarm new
         swap >nanoseconds >>interval
-        swap >nanoseconds nano-count + >>start
-        swap >>quot ;
+        swap >nanoseconds nano-count +
+            [ >>start ] [ >>iteration-scheduled ] bi
+        swap >>quot ; inline
 
 : register-alarm ( alarm -- )
     dup start>> alarms get-global heap-push* drop

    { quot callable initial: [ ] }
    { start integer }
    interval
    { previous-iteration-begin integer }
    { iteration-begin integer }
    { stop? boolean } ;

SYMBOL: alarms

: alarm-expired? ( alarm n -- ? )
    [ start>> ] dip <= ;

: set-next-alarm-time ( alarm -- alarm )
    ! start + ceiling((now - start) / interval) * interval
    nano-count 
    over start>> -
    over interval>> / ceiling
    over interval>> *
    over start>> + >>iteration-scheduled ; inline

DEFER: call-alarm-loop

: loop-alarm ( alarm -- )
    nano-count over
    [ iteration-scheduled>> - ] [ interval>> ] bi <
    [ set-next-alarm-time ] dip [
        [ iteration-scheduled>> sleep-until ]
        [ call-alarm-loop ] bi
    ] [
        0 sleep-until call-alarm-loop
    ] if ;
