! Copyright (C) 2005, 2008 Slava Pestov, Doug Coleman. ! See http://factorcode.org/license.txt for BSD license. USING: accessors assocs boxes calendar combinators.short-circuit fry heaps init kernel math.order namespaces quotations threads ; IN: alarms TUPLE: alarm { quot callable initial: [ ] } { time timestamp } interval { entry box } ; ( quot time frequency -- alarm ) check-alarm alarm boa ; : register-alarm ( alarm -- ) [ dup time>> alarms get-global heap-push* ] [ entry>> >box ] bi notify-alarm-thread ; : alarm-expired? ( alarm now -- ? ) [ time>> ] dip before=? ; : reschedule-alarm ( alarm -- ) dup '[ _ interval>> time+ now max ] change-time register-alarm ; : call-alarm ( alarm -- ) [ entry>> box> drop ] [ quot>> "Alarm execution" spawn drop ] [ dup interval>> [ reschedule-alarm ] [ drop ] if ] tri ; : (trigger-alarms) ( alarms now -- ) over heap-empty? [ 2drop ] [ over heap-peek drop over alarm-expired? [ over heap-pop drop call-alarm (trigger-alarms) ] [ 2drop ] if ] if ; : trigger-alarms ( alarms -- ) now (trigger-alarms) ; : next-alarm ( alarms -- timestamp/f ) dup heap-empty? [ drop f ] [ heap-peek drop time>> ] if ; : alarm-thread-loop ( -- ) alarms get-global dup next-alarm sleep-until trigger-alarms ; : cancel-alarms ( alarms -- ) [ heap-pop-all [ nip entry>> box> drop ] assoc-each ] when* ; : init-alarms ( -- ) alarms [ cancel-alarms ] change-global [ alarm-thread-loop t ] "Alarms" spawn-server alarm-thread set-global ; [ init-alarms ] "alarms" add-init-hook PRIVATE> : add-alarm ( quot time frequency -- alarm ) [ register-alarm ] keep ; : later ( quot duration -- alarm ) hence f add-alarm ; : every ( quot duration -- alarm ) [ hence ] keep add-alarm ; : cancel-alarm ( alarm -- ) entry>> [ alarms get-global heap-delete ] if-box? ;