marketplace-2014/process.rkt

142 lines
5.0 KiB
Racket
Raw Normal View History

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))
(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: