2014-08-06 19:16:50 +00:00
|
|
|
#lang racket/base
|
2013-03-29 03:00:29 +00:00
|
|
|
|
|
|
|
(require racket/match)
|
2014-08-06 19:16:50 +00:00
|
|
|
(require "structs.rkt")
|
2013-03-29 03:00:29 +00:00
|
|
|
(require "roles.rkt")
|
|
|
|
(require "vm.rkt")
|
2014-08-06 19:16:50 +00:00
|
|
|
(require "log.rkt")
|
|
|
|
(require "quasiqueue.rkt")
|
2013-03-29 03:00:29 +00:00
|
|
|
|
|
|
|
(provide send-to-user
|
|
|
|
send-to-user*
|
|
|
|
action-tree->quasiqueue
|
|
|
|
quit-interruptk
|
|
|
|
run-ready
|
|
|
|
notify-route-change-vm)
|
|
|
|
|
|
|
|
(define-syntax-rule (send-to-user p (e) failure-result enclosed-expr)
|
|
|
|
(send-to-user* (process-debug-name p) (process-pid p) (e) failure-result enclosed-expr))
|
|
|
|
|
|
|
|
(define-syntax-rule (send-to-user* debug-name pid (e) failure-result enclosed-expr)
|
2014-08-06 19:16:50 +00:00
|
|
|
(with-handlers ([exn:fail? (lambda (e)
|
2013-03-29 03:00:29 +00:00
|
|
|
(if (exn? e)
|
2013-05-30 21:54:53 +00:00
|
|
|
(marketplace-log 'error "Process ~v(~v):~n~a~n"
|
|
|
|
debug-name pid (exn-message e))
|
|
|
|
(marketplace-log 'error "Process ~v(~v):~n~v~n"
|
|
|
|
debug-name pid e))
|
2013-03-29 03:00:29 +00:00
|
|
|
failure-result)])
|
2013-05-30 21:54:53 +00:00
|
|
|
(marketplace-log 'debug "Entering process ~v(~v)" debug-name pid)
|
2013-04-11 19:19:31 +00:00
|
|
|
(define result enclosed-expr)
|
2013-05-30 21:54:53 +00:00
|
|
|
(marketplace-log 'debug "Leaving process ~v(~v)" debug-name pid)
|
2013-04-11 19:19:31 +00:00
|
|
|
result))
|
2013-03-29 03:00:29 +00:00
|
|
|
|
2014-08-06 19:16:50 +00:00
|
|
|
;; action-tree->quasiqueue : (All (State) (ActionTree State) -> (QuasiQueue (Action State)))
|
|
|
|
;; TODO: simplify
|
2013-03-29 03:00:29 +00:00
|
|
|
(define (action-tree->quasiqueue t)
|
2014-08-06 19:16:50 +00:00
|
|
|
(let loop ((revacc '()) (t t))
|
2013-03-29 03:00:29 +00:00
|
|
|
(cond
|
|
|
|
[(pair? t) (loop (loop revacc (car t)) (cdr t))]
|
|
|
|
[(or (null? t) (eq? t #f) (void? t)) revacc]
|
|
|
|
[else (cons t revacc)])))
|
|
|
|
|
|
|
|
;; Split out to provide a syntactic location to define State in
|
2014-08-06 19:16:50 +00:00
|
|
|
;; quit-interruptk : Reason -> (All (State) State -> (Transition State))
|
2013-03-29 03:00:29 +00:00
|
|
|
(define ((quit-interruptk e) old-process-state)
|
|
|
|
(transition old-process-state (quit #f e)))
|
|
|
|
|
2014-08-06 19:16:50 +00:00
|
|
|
;; run-ready : (All (State) (process State) (InterruptK State) -> (process State))
|
2013-03-29 03:00:29 +00:00
|
|
|
(define (run-ready p interruptk)
|
|
|
|
(define old-state (process-state p))
|
|
|
|
(match-define (transition new-state actions)
|
2014-08-06 19:16:50 +00:00
|
|
|
(send-to-user p (e) (transition old-state (quit #f e))
|
2013-03-29 03:00:29 +00:00
|
|
|
(interruptk old-state)))
|
|
|
|
(struct-copy process p
|
|
|
|
[state new-state]
|
|
|
|
[pending-actions (quasiqueue-append (process-pending-actions p)
|
|
|
|
(action-tree->quasiqueue actions))]))
|
|
|
|
|
2014-08-06 19:16:50 +00:00
|
|
|
;; notify-route-change-self : (All (SNew)
|
|
|
|
;; (process SNew)
|
|
|
|
;; (endpoint SNew)
|
|
|
|
;; (Role -> EndpointEvent)
|
|
|
|
;; ->
|
|
|
|
;; (process SNew))
|
2013-04-11 19:20:02 +00:00
|
|
|
(define (notify-route-change-self pn en flow->notification)
|
|
|
|
(define endpointso (process-endpoints pn))
|
|
|
|
(for/fold ([pn pn]) ([eido (in-hash-keys endpointso)])
|
|
|
|
(define eo (hash-ref endpointso eido))
|
|
|
|
(cond
|
|
|
|
[(role-intersection (endpoint-role eo) (endpoint-role en))
|
|
|
|
=> (lambda (intersecting-topic)
|
|
|
|
(define flow-toward-o (refine-role (endpoint-role en) intersecting-topic))
|
|
|
|
(define flow-toward-n (refine-role (endpoint-role eo) intersecting-topic))
|
|
|
|
(invoke-handler-if-visible (invoke-handler-if-visible pn
|
|
|
|
eo
|
|
|
|
flow-toward-o
|
|
|
|
flow->notification)
|
|
|
|
en
|
|
|
|
flow-toward-n
|
|
|
|
flow->notification))]
|
|
|
|
[else pn])))
|
|
|
|
|
2014-08-06 19:16:50 +00:00
|
|
|
;; notify-route-change-process : (All (SOld SNew)
|
|
|
|
;; (process SOld)
|
|
|
|
;; (process SNew)
|
|
|
|
;; (endpoint SNew)
|
|
|
|
;; (Role -> EndpointEvent)
|
|
|
|
;; -> (values (process SOld)
|
|
|
|
;; (process SNew)))
|
2013-03-29 03:00:29 +00:00
|
|
|
(define (notify-route-change-process po pn en flow->notification)
|
|
|
|
(define endpointso (process-endpoints po))
|
|
|
|
(for/fold ([po po]
|
|
|
|
[pn pn])
|
|
|
|
([eido (in-hash-keys endpointso)])
|
|
|
|
(define eo (hash-ref endpointso eido))
|
|
|
|
(cond
|
|
|
|
[(role-intersection (endpoint-role eo) (endpoint-role en))
|
|
|
|
=> (lambda (intersecting-topic)
|
|
|
|
(define flow-toward-o (refine-role (endpoint-role en) intersecting-topic))
|
|
|
|
(define flow-toward-n (refine-role (endpoint-role eo) intersecting-topic))
|
|
|
|
(values (invoke-handler-if-visible po eo flow-toward-o flow->notification)
|
|
|
|
(invoke-handler-if-visible pn en flow-toward-n flow->notification)))]
|
|
|
|
[else
|
|
|
|
(values po pn)])))
|
|
|
|
|
2014-08-06 19:16:50 +00:00
|
|
|
;; invoke-handler-if-visible : (All (State)
|
|
|
|
;; (process State)
|
|
|
|
;; (endpoint State)
|
|
|
|
;; Role
|
|
|
|
;; (Role -> EndpointEvent)
|
|
|
|
;; ->
|
|
|
|
;; (process State))
|
2013-03-29 03:00:29 +00:00
|
|
|
(define (invoke-handler-if-visible p ep flow flow->notification)
|
|
|
|
(if (flow-visible? (endpoint-role ep) flow)
|
|
|
|
(run-ready p (send-to-user p (e) (quit-interruptk e)
|
|
|
|
((endpoint-handler ep) (flow->notification flow))))
|
|
|
|
p))
|
|
|
|
|
2014-08-06 19:16:50 +00:00
|
|
|
;; notify-route-change-vm : (All (SNew)
|
|
|
|
;; (process SNew)
|
|
|
|
;; (endpoint SNew)
|
|
|
|
;; (Role -> EndpointEvent)
|
|
|
|
;; vm
|
|
|
|
;; -> (values (process SNew)
|
|
|
|
;; vm))
|
2013-03-29 03:00:29 +00:00
|
|
|
(define (notify-route-change-vm pn en flow->notification state)
|
|
|
|
(define old-processes (vm-processes state))
|
|
|
|
(define-values (final-pn new-processes)
|
2014-08-06 19:16:50 +00:00
|
|
|
(for/fold ([pn (notify-route-change-self pn en flow->notification)]
|
|
|
|
[new-processes #hash()])
|
2013-03-29 03:00:29 +00:00
|
|
|
([pid (in-hash-keys old-processes)])
|
|
|
|
(define wp (hash-ref old-processes pid))
|
|
|
|
(apply values
|
2014-08-06 19:16:50 +00:00
|
|
|
(let ((po wp))
|
2013-03-29 03:00:29 +00:00
|
|
|
(let-values (((po pn) (notify-route-change-process po pn en flow->notification)))
|
2014-08-06 19:16:50 +00:00
|
|
|
(list pn (hash-set new-processes pid po)))))))
|
2013-03-29 03:00:29 +00:00
|
|
|
(values final-pn
|
|
|
|
(struct-copy vm state [processes new-processes])))
|
|
|
|
|
|
|
|
;;; Local Variables:
|
|
|
|
;;; eval: (put 'send-to-user 'scheme-indent-function 3)
|
|
|
|
;;; End:
|