-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathscheduler.scm
152 lines (136 loc) · 4.26 KB
/
scheduler.scm
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
;
;; Non-real-time portable version of music system described in
;; "Music Programming in Scheme". Lee Richard Boynton. ICMC 1992.
;; Copyright (c) 1992-2000 Lee Richard Boynton.
;
(provide 'scheduler)
(require 'macros)
(define *now* 0)
(define *waiting* '())
(define *ready* '())
(define *signals* '())
(define *defaults* '())
(define *global-defaults* '())
(define (schedule continuation timeout cue)
(let* ((time (+ *now* timeout))
(element (list time continuation cue #f *defaults*)))
(if (or (null? *waiting*) (<= time (caar *waiting*)))
(set! *waiting* (cons element *waiting*))
(let ((tmp (cdr *waiting*)))
(if (null? tmp)
(set-cdr! *waiting* (cons element '()))
(let loop ((tail *waiting*) (tail-cdr tmp))
(if (<= time (caar tail-cdr))
(set-cdr! tail (cons element tail-cdr))
(if (null? (cdr tail-cdr))
(set-cdr! tail-cdr (cons element '()))
(loop (cdr tail) (cdr tail-cdr))))))))))
(define (wait-for-time then)
(let ((delay (- then (real-time))))
(if (> delay 0) (system:pause delay))
then))
(define *base* (system:timestamp))
(define *latency* 1000)
(define (real-time) (- (system:timestamp) *base*))
(define (now) *now*)
(define (context-switch)
(let next-context ((ready *ready*))
(if (not (null? ready))
(let ((task (car ready)))
(set! *now* (car task))
(set! *ready* (cdr ready))
(set! *defaults* (cadddr (cdr task)))
((cadr task) (cadddr task))))
(if (pair? *signals*)
(let signal-loop ((signal (car *signals*)))
(set! *signals* (cdr *signals*))
(let ((cue (car signal))
(value (cdr signal))
(tail *waiting*))
(let loop ((w *waiting*))
(if (not (null? w))
(if (eq? (caddar w) cue)
(let ((tmp (cdr w)))
(if (eq? w *waiting*)
(set! *waiting* tmp)
(set-cdr! tail tmp))
(set-cdr! w *ready*)
(set! *ready* w)
(set-car! (car w) *now*)
(set-car! (cdddar w) value)
(loop tmp))
(begin
(set! tail w)
(loop (cdr w)))))))
(if (pair? *signals*)
(signal-loop (car *signals*))
(next-context *ready*))))
(if (not (null? *waiting*))
(let ((time (caar *waiting*)))
(wait-for-time time)
(let wait-loop ((e (car *waiting*)))
(set! *waiting* (cdr *waiting*))
(set! *ready* (cons e *ready*))
(if (and (not (null? *waiting*))
(<= (caar *waiting*) time))
(wait-loop (car *waiting*))))
(next-context *ready*)))))
(define (unique-cue) (make-vector 0))
(define (reset-scheduler)
(set! *base* (system:timestamp))
(set! *latency* 1000)
(set! *now* 0)
(set! *waiting* '())
(set! *ready* '())
(set! *signals* '())
(set! *defaults* *global-defaults*))
(define (wait cue timeout)
(call-with-current-continuation
(lambda (continuation)
(schedule continuation timeout cue)
(context-switch))))
(define (sleep delay)
(wait (unique-cue) delay))
(define-syntax parallel
(syntax-rules ()
((parallel <exp1> <exp2> ...)
(let ((count (length '(<exp1> <exp2> ...))))
(call-with-current-continuation
(lambda (join)
(schedule (lambda (ignore) <exp1> (join #t)) 0 (unique-cue))
(schedule (lambda (ignore) <exp2> (join #t)) 0 (unique-cue))
...))
(if (> count 0)
(begin
(set! count (- count 1))
(context-switch)))))))
(define (signal cue value)
(call-with-current-continuation
(lambda (continuation)
(schedule continuation 0 cue)
(set! *signals* (cons (cons cue value) *signals*))
(context-switch))))
(define-syntax define-default
(syntax-rules ()
((default <name> <value>)
(let ((tmp (cons '<name> <value>)))
(set! *global-defaults* (cons tmp *global-defaults*))
(set! *defaults* (cons tmp *defaults*))))))
(define-syntax default
(syntax-rules ()
((default name)
(let ((binding (assq 'name *defaults*)))
(if binding
(cdr binding)
(error "unbound default:" 'name))))))
(define-syntax let-default
(syntax-rules ()
((let-default ((<name1> <val1>) (<name2> <val2>) ...)
<expr1> <expr2> ...)
(let ((saved-defaults *defaults*) (result #f))
(set! *defaults* (cons (cons '<name1> <val1>) *defaults*))
(set! *defaults* (cons (cons '<name2> <val2>) *defaults*))
...
(set! result (begin <expr1> <expr2> ...))
(set! *defaults* saved-defaults)
result))))