-
Notifications
You must be signed in to change notification settings - Fork 5
/
Copy pathrecv.scm
65 lines (60 loc) · 2.64 KB
/
recv.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
(import (only: match match/action)
exception)
;; All hail the RECV form
(define-syntax recv
(sc-macro-transformer
(lambda (form env)
(let ((clauses (cdr form)))
;; check the last clause to see if it's a timeout
(let ((sesualc (reverse clauses)))
(if (and (pair? (car sesualc))
(eq? (caar sesualc) 'after))
(let ((clauses (map (lambda (x)
(make-syntactic-closure env '() x))
(reverse (cdr sesualc))))
;; the code to compute the timeout
(init (make-syntactic-closure
env
'()
(cadar sesualc)))
;; the code to be executed on a timeout
(on-timeout (map (lambda (x)
(make-syntactic-closure env '() x))
(cddar sesualc))))
;; RECV code when there is a timeout
`(let ((timeout ,init))
(with-exception-catcher
(lambda (e)
(if (mailbox-receive-timeout-exception? e)
(begin
(thread-mailbox-rewind)
,@on-timeout)
(raise e)))
(lambda ()
(let loop ((msg (thread-mailbox-next timeout)))
(match/action
(thread-mailbox-extract-and-rewind)
(loop
(thread-mailbox-next timeout))
msg
;; extra clause to handle system events
(event
(where (termite-exception? event))
(handle-exception-message event))
;; the user clauses
,@clauses))))))
;; RECV code when there is no timeout
`(let loop ((msg (thread-mailbox-next)))
(match/action
(thread-mailbox-extract-and-rewind)
(loop
(thread-mailbox-next))
msg
;; extra clause to handle system events
(event
(where (termite-exception? event))
(handle-exception-message event))
;; the user clauses
,@(map (lambda (x)
(make-syntactic-closure env '() x))
clauses)))))))))