factor/library/threads.factor

90 lines
2.2 KiB
Factor
Raw Normal View History

! Copyright (C) 2004, 2005 Slava Pestov.
2005-02-07 18:27:55 -05:00
! Copyright (C) 2005 Mackenzie Straight.
! See http://factor.sf.net/license.txt for BSD license.
2004-08-20 21:26:25 -04:00
IN: threads
2005-08-23 15:50:32 -04:00
USING: errors hashtables io-internals kernel lists math
namespaces queues sequences vectors ;
2004-08-20 21:26:25 -04:00
2005-08-23 15:50:32 -04:00
! Co-operative multitasker.
: run-queue ( -- queue ) \ run-queue global hash ;
: schedule-thread ( quot -- ) run-queue enque ;
: sleep-queue ( -- vec ) \ sleep-queue global hash ;
: sleep-queue* ( -- vec )
sleep-queue dup [ 2car swap - ] nsort ;
: sleep-time ( sorted-queue -- ms )
dup empty? [ drop -1 ] [ peek car millis - 0 max ] ifte ;
DEFER: next-thread
: do-sleep ( -- quot )
sleep-queue* dup sleep-time dup 0 =
[ drop pop ] [ nip io-multiplex next-thread ] ifte ;
2005-02-07 18:04:49 -05:00
2004-08-20 21:26:25 -04:00
: next-thread ( -- quot )
2005-08-23 15:50:32 -04:00
run-queue dup queue-empty? [ drop do-sleep ] [ deque ] ifte ;
: stop ( -- ) next-thread call ;
: yield ( -- ) [ schedule-thread stop ] callcc0 ;
: sleep ( ms -- )
millis + [ cons sleep-queue push stop ] callcc0 drop ;
: in-thread ( quot -- )
[
schedule-thread
[ ] set-catchstack { } set-callstack
try stop
] callcc0 drop ;
2005-08-23 20:27:42 -04:00
TUPLE: timer object delay last ;
: timer-now millis swap set-timer-last ;
C: timer ( object delay -- timer )
[ set-timer-delay ] keep
[ set-timer-object ] keep
dup timer-now ;
GENERIC: tick ( ms object -- )
: timers ( -- hash ) \ timers global hash ;
: add-timer ( object delay -- )
over >r <timer> r> timers set-hash ;
2005-08-23 20:27:42 -04:00
: remove-timer ( object -- ) timers remove-hash ;
: restart-timer ( object -- )
timers hash [ timer-now ] when* ;
: next-time ( timer -- ms ) dup timer-delay swap timer-last + ;
: advance-timer ( ms timer -- delay )
#! Outputs the time since the last firing.
[ timer-last - 0 max ] 2keep set-timer-last ;
: do-timer ( ms timer -- )
#! Takes current time, and a timer. If the timer is set to
#! fire, calls its callback.
dup next-time pick <= [
2005-08-24 00:30:07 -04:00
[ advance-timer ] keep timer-object tick
2005-08-23 20:27:42 -04:00
] [
2drop
] ifte ;
: do-timers ( -- )
millis timers hash-values [ do-timer ] each-with ;
2005-08-24 00:30:07 -04:00
: init-threads ( -- )
global [
<queue> \ run-queue set
2005-08-25 15:27:38 -04:00
{ } clone \ sleep-queue set
{{ }} clone \ timers set
2005-08-24 00:30:07 -04:00
] bind ;