#:use-module (ice-9 match)
#:use-module (ice-9 pretty-print)
#:use-module (8sync agenda)
+ #:use-module (8sync rmeta-slot)
#:export (;; utilities... ought to go in their own module
big-random-number
big-random-number-string
(define (actor-inheritable-message-handler actor message)
(define action (message-action message))
- (define (find-message-handler return)
- (for-each (lambda (this-class)
- (define actions
- (or (and (class-slot-definition this-class 'actions)
- (class-slot-ref this-class 'actions))
- '()))
- (for-each (match-lambda
- ((action-name . method)
- (when (eq? action-name action)
- (return method))))
- actions))
- (class-precedence-list (class-of actor)))
+ (define method
+ (class-rmeta-ref (class-of actor) 'actions action
+ #:equals? eq? #:cache-set! hashq-set!
+ #:cache-ref hashq-ref))
+ (unless method
(throw 'action-not-found
"No appropriate action handler found for actor"
#:action action
#:actor actor
#:message message))
- (define method
- (call/ec find-message-handler))
(apply method actor message (message-body message)))
(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
to come after class definition."
- (list
- (cons (quote symbol)
- (wrap-apply method)) ...))
+ (make-rmeta-slot
+ (list (cons (quote symbol)
+ (wrap-apply method)) ...)))
(define-class <actor> ()
;; An address object
#:allocation #:each-subclass
#:getter actor-message-handler)
+ ;; valid values are:
+ ;; - #t as in, send the init message, but don't wait (default)
+ ;; - 'wait, as in wait on the init message
+ ;; - #f as in don't bother to init
+ (should-init #:init-value #t
+ #:allocation #:each-subclass)
+
;; This is the default, "simple" way to inherit and process messages.
(actions #:init-value (build-actions
;; Default init method is to do nothing.
(hash-map->list (lambda (actor-id actor) actor-id)
(hive-actor-registry hive)))
(for-each (lambda (actor-id)
- ;; @@: This could maybe just be <-, but we want actors
- ;; to be used to the expectation in all circumstances
- ;; that their init method is "waited on".
- (<-wait actor-id '*init*))
+ (let* ((actor (hash-ref (hive-actor-registry hive)
+ actor-id)))
+ (match (slot-ref actor 'should-init)
+ (#f #f)
+ ('wait
+ (<-wait actor-id '*init*))
+ (_
+ (<- actor-id '*init*)))))
actor-ids))
(define-method (hive-handle-failed-forward (hive <hive>) message)
(actor (apply make actor-class
#:hive hive
#:id actor-id
- init-args)))
+ init-args))
+ (actor-should-init (slot-ref actor 'should-init)))
(hive-register-actor! hive actor)
- ;; Wait on actor to init
- (when send-init?
- (<-wait actor-id '*init*))
+ ;; Maybe run actor init method
+ (when (and send-init? actor-should-init)
+ (let ((send-method
+ (if (eq? actor-should-init 'wait)
+ <-wait <-)))
+ (send-method actor-id '*init*)))
;; return the actor id
actor-id))