simple-message-id-generator
<actor>
+ <reentrant-actor>
actor-id
actor-message-handler
;;; Main actor implementation
;;; =========================
-(define (actor-inheritable-message-handler actor message)
+(define (actor-reentrant-message-handler actor message)
(define action (message-action message))
(define method
(class-rmeta-ref (class-of actor) 'actions action
#:message message))
(apply method actor message (message-body message)))
+(define (actor-non-reentrant-message-handler actor message)
+ (let* ((queue (actor-message-q actor))
+ (messages? (pair? queue)))
+ (warn 'queue-size: (length queue))
+ (set! queue (append queue (list message)))
+ (unless messages?
+ (let loop ()
+ (warn 'handle-message: (message-action message))
+ (actor-reentrant-message-handler actor (car queue))
+ (set! queue (cdr queue))
+ (unless (null? queue)
+ (loop))))))
+
(define-syntax-rule (build-actions (symbol method) ...)
"Construct an alist of (symbol . method), where the method is wrapped
with wrap-apply to facilitate live hacking and allow the method definition
(hive #:init-keyword #:hive
#:accessor actor-hive)
;; How we receive and process new messages
- (message-handler #:init-value actor-inheritable-message-handler
+ (message-handler #:init-value actor-non-reentrant-message-handler
;; @@: There's no reason not to use #:class instead of
;; #:each-subclass anywhere in this file, except for
;; Guile bug #25211 (#:class is broken in Guile 2.2)
(*init* (const #f))
;; Default cleanup method is to do nothing.
(*cleanup* (const #f)))
- #:allocation #:each-subclass))
+ #:allocation #:each-subclass)
+
+ (message-q #:init-value '() #:accessor actor-message-q))
+
+(define-class <reentrant-actor> (<actor>))
+
+(define-method (initialize (o <reentrant-actor>) args)
+ (next-method)
+ (slot-set! o 'message-handler actor-reentrant-message-handler))
;;; Addresses are vectors where the first part is the actor-id and
;;; the second part is the hive-id. This works well enough... they