1 ;; Simple Actor Machine
3 ;; Houses a population of actors which can communicate using messages
4 ;; with actors on the same machine or other machines via the network.
16 (define (make-machine host port)
18 (define (machine-host m) (car m))
19 (define (machine-port m) (cdr m))
21 (define this-machine (make-machine "localhost" 1234))
24 (let ((mutex (make-mutex "actor id mutex"))
30 (set! next-id (+ next-id 1))
34 (define (address-id address) (car address))
35 (define (address-machine address) (cdr address))
36 (define (make-address id machine)
39 (define (address-local? address)
40 (equal? (address-machine address)
43 (define actor-table (make-hash-table))
45 (define (make-actor beh)
46 (let* ((id (next-actor-id)))
47 (hash-table-set! actor-table id beh)
48 (make-address id this-machine)))
50 (define (deliver-message address . message)
51 (let ((id (address-id address)))
52 (let ((behaviour (hash-table-ref/default actor-table id '())))
54 (print "Warning: discarded message" message " to unknown actor " address)
55 (match (apply (hash-table-ref actor-table id) (cons address message))
56 ('done (hash-table-delete! actor-table id))
58 (new-beh (hash-table-set! actor-table id new-beh)))))))
62 (define local-queue-mutex (make-mutex "message queue"))
63 (define message-available-mutex (make-mutex "message available"))
64 (mutex-lock! message-available-mutex #f #f)
65 (define local-queue (make-fifo))
67 (define (send-message address . message)
68 (apply (if (address-local? address)
71 (cons address message)))
73 (define (send-local-message address . message)
74 (mutex-lock! local-queue-mutex)
75 (fifo-push local-queue (cons address message))
76 (mutex-unlock! message-available-mutex)
77 (mutex-unlock! local-queue-mutex))
79 (define (send-network-message address . message)
80 (let ((s (udp-open-socket))
81 (machine (address-machine address)))
84 (machine-host machine)
85 (machine-port machine))
87 (udp-close-socket s)))
89 (define (next-local-message)
91 (mutex-lock! message-available-mutex #f #f)
92 (mutex-lock! local-queue-mutex)
93 (set! res (fifo-pop local-queue))
94 (if (not (fifo-empty? local-queue))
95 (mutex-unlock! message-available-mutex))
96 (mutex-unlock! local-queue-mutex)
99 (define (start-scheduler)
103 (apply deliver-message (next-local-message))
108 (define reader-queue-mutex (make-mutex "reader queue"))
109 (define reader-available-mutex (make-mutex "reader available"))
110 (mutex-lock! reader-available-mutex #f #f)
111 (define reader-queue (make-fifo))
114 (make-actor (lambda (self . message)
115 (mutex-lock! reader-queue-mutex)
116 (fifo-push reader-queue (car message))
117 (mutex-unlock! reader-available-mutex)
118 (mutex-unlock! reader-queue-mutex)
121 (define (next-reader)
123 (mutex-lock! reader-available-mutex #f #f)
124 (mutex-lock! reader-queue-mutex)
125 (set! res (fifo-pop reader-queue))
126 (if (not (fifo-empty? reader-queue))
127 (mutex-unlock! reader-available-mutex))
128 (mutex-unlock! reader-queue-mutex)
131 (define (start-console)
133 (let ((reader (next-reader)))
134 (##sys#thread-block-for-i/o! (current-thread) 0 #t)
136 (send-message reader (read-line)))
143 (make-actor (lambda (self . message)
146 (print "## System actor received shutdown message.")
149 (('println strings ...)
150 (apply print strings)
156 (send-message system 'println "Hello, what is your name?")
157 (send-message console
158 (make-actor (lambda (self . message)
161 (send-message system 'println "Hello, " name "!")
167 (send-message system 'shutdown)))
172 ;; (thread-join! scheduler-thread)