<<- is broken in several ways since adding promises support
At and before commit a8fedcd7 the <<-
operator worked fine. The way it worked then was that messages had ids, and some messages would "request to be replied to" because the actor was holding onto a continuation that could be resumed once a response came in. After the merging of the E-like promises code, this is no longer the case; <<-
is now quite simply built off of the existing promises infrastructure:
;; slightly simplified version of <<-
(define <<-
(make-keyword-procedure
(lambda (kws kw-args to sys-method . args)
(define resume-data
(call-with-composable-continuation
(lambda (k)
(abort-current-continuation actor-prompt-tag k to 'handle
kws kw-args args))
actor-prompt-tag))
(match resume-data
[(vector 'resume-values vals)
(apply values vals)]
[(vector 'error err)
;; TODO: Do we really just want to re-raise the error this way
(raise err)]))))
(define hive%
(class object%
(super-new)
;; ... other hive things go here ...
(define (handle-message actor actor-address msg)
;; Set up initial escape and capture prompts, along with error handler
(call-with-continuation-prompt
(lambda ()
;; main message handling code goes here
)
actor-prompt-tag
(lambda (k to sys-method kws kw-args args)
(current-actable (new actable%))
(on (keyword-apply <-sys kws kw-args to sys-method args)
;; resume continuation
(lambda vals
(k (vector 'resume-values vals)))
#:catch
(lambda (err)
(k (vector 'error err))))
(current-actable #f))))
;; ...
))
However, a couple of serious problems have been introduced which can be demonstrated by the following code:
(require goblins)
(time
;; kick off and wait for this actor to complete
(<<-
(spawn
(lambda ()
;; simple no-op actor
(define foop
(spawn (lambda () 'no-op)))
;; call this actor many times with <<-
(for ([i (in-range 3000)])
(<<- foop))))))
Before the promises refactor, this would complete nearly instantaneously and would use nearly no memory. After the promises refactor, three major problems have been introduced:
- It's very slow
- It leaks memory like crazy, within the realm of gigabytes
- It also appears to break Racket itself with the error "Dynamic-wind record doesn't match prompt!"
Given that the latter error indicates that I'm tripping up some internal Racket bug, I'm uncertain if this is due to the fault of my own code or some internal Racket bug.