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))
23 (define next-actor-id 1)
25 (define (address-id address) (car address))
26 (define (address-machine address) (cdr address))
27 (define (make-address id machine)
30 (define (address-local? address)
31 (equal? (address-machine address)
34 (define actor-table (make-hash-table))
36 (define (make-actor beh)
37 (let* ((id next-actor-id))
38 (hash-table-set! actor-table id beh)
39 (make-address id this-machine)))
41 (define (deliver-message address . message)
42 (let ((id (address-id address)))
43 (let ((behaviour (hash-table-ref/default actor-table id '())))
45 (print "Warning: discarded message" message " to unknown actor " address)
46 (match (apply (hash-table-ref actor-table id) (cons address message))
47 ('done (hash-table-delete! actor-table actor))
49 (new-beh (hash-table-set! actor-table actor new-beh)))))))
53 (define local-queue-mutex (make-mutex "message queue"))
54 (define message-available-mutex (make-mutex "message available"))
55 (mutex-lock! message-available-mutex #f #f)
56 (define local-queue (make-fifo))
58 (define (send-message address . message)
59 (apply (if (address-local? address)
64 (define (send-local-message address . message)
65 (mutex-lock! local-queue-mutex)
66 (fifo-push local-queue (cons address message))
67 (mutex-unlock! message-available-mutex)
68 (mutex-unlock! local-queue-mutex))
70 (define (send-network-message address . message)
71 (let ((s (udp-open-socket))
72 (machine (address-machine address)))
75 (machine-host machine)
76 (machine-port machine))
78 (udp-close-socket s)))
80 (define (next-local-message)
82 (mutex-lock! message-available-mutex #f #f)
83 (mutex-lock! local-queue-mutex)
84 (set! res (fifo-pop local-queue))
85 (if (not (fifo-empty? local-queue))
86 (mutex-unlock! message-available-mutex))
87 (mutex-unlock! local-queue-mutex)
90 (define scheduler-thread
93 (let loop ((next-addressed-message (next-local-message)))
94 (apply deliver-message next-addressed-message)
95 (loop (next-local-message))))))
100 (thread-start! scheduler-thread)
103 (make-actor (lambda (self . message)
104 (apply print message)
108 (send-message println "Hello, world!")
110 (thread-join! scheduler-thread)