|(require place-controller)||package: place-controller|
This package simplifies use of places. Specifically, it helps you read and write discrete values from place channels and related ports through a single generator-like procedure. That procedure is called a place controller.
#lang racket/base (provide main) (require racket/place) (define (main pch) (with-handlers ([exn:break? (λ (e) (exit 0))]) (let loop () (case (sync/enable-break pch) [(say-hi) (displayln "What's your name?") (printf "Hi, ~a!~n" (read-line)) (flush-output) (place-channel-put pch "omg someone said hi to me")] [else (displayln "Huh?") (flush-output)]) (loop))))
#lang racket/base (require racket/runtime-path place-controller) (define-runtime-path worker.rkt "./worker.rkt") (define $ (make-place-controller/dynamic-place* worker.rkt #:read-stdout read-line)) (sync ($ 'moo)) ; (from-stdout #<procedure:place-resources> "Huh?") (sync ($ 'say-hi)) ; (from-stdout #<procedure:place-resources> "What's your name?") ($ (λ (o) (displayln "Mark" o))) ; Waits for these values, which may come in either order: ; - (from-stdout #<procedure:place-resources> "Hi, Mark!") ; - (from-place-channel #<procedure:place-resources> "omg someone said hi to me") (sync ($)) (sync ($)) ; Once you stop the controller, it will ; only produce the last value. ; (detach-clean 0) (sync ($ 'stop)) (sync ($)) (sync ($))
The controller reads values from each possible source in no particular order, except that a place-detach-envelope always comes last.
(struct place-resources ( id controller pch sink-stdin source-stdout source-stderr)) id : any/c controller : place-controller/c pch : place? sink-stdin : (or/c #f output-port?) source-stdout : (or/c #f input-port?) source-stderr : (or/c #f input-port?)
sender : place-resources? value : any/c
sender is useful for identifying the resources used to produce a given value, and the predicates for all subtypes of place-datum-envelope indicate which resource is responsible for the message.
resources : place-resources?
completion-value : exact-integer?
(make-place-controller pch [ #:id id #:source-stdout source-stdout #:source-stderr source-stderr #:sink-stdin sink-stdin #:clean-up? clean-up? #:terminate-alarm-ms terminate-alarm-ms #:read-stdout read-stdout #:read-stderr read-stderr]) → place-controller/c pch : place? id : any/c = #f source-stdout : (or/c #f input-port?) = #f source-stderr : (or/c #f input-port?) = #f sink-stdin : (or/c #f output-port?) = #f clean-up? : any/c = #t terminate-alarm-ms : positive? = 200 read-stdout : (-> input-port? any/c) = read read-stderr : (-> input-port? any/c) = read
All applications of P return a synchronizable event as described in place-controller/c. If the synchronization result of an event is an instance of place-detach-envelope, then (P) will only ever produce that same instance.
If P is applied to a value, it has a side-effect before returning a synchronizable event:
(P (lambda (sink-stdin) ...)) calls the given procedure with sink-stdin for the effect of writing content to the place’s current-input-port. After the procedure finishes, the output is immediately flushed.
(P 'stop) concludes use of the place. All applications of (P) will henceforth return a final value depending on clean-up?, with no other effects (Explained below).
Once P is ready to stop managing a place, it will prepare a final, constant synchronization result. If clean-up? is #f, then P will use an instance of detach-dirty. Otherwise, P will evaluate (place-break pch). It will then wait up to terminate-alarm-ms milliseconds after the time it received a value from the place to terminate on its own. If it does not, the place will be forcefully terminated using place-kill. Finally, source-stdout, source-stderr, and sink-stdin will be closed. P will henceforth return detach-clean.
If P finds that the underlying place has terminated before encountering 'stop, then P will close all related ports regardless of the value of clean-up?. In this case, P will finish with an instance of detach-clean.
(make-place-controller/dynamic-place* module-path [ start-name #:id id #:clean-up? clean-up? #:terminate-alarm-ms terminate-alarm-ms #:read-stdout read-stdout #:read-stderr read-stderr]) → place-controller/c module-path : (or/c module-path? path?) start-name : symbol? = 'main id : any/c = #f clean-up? : any/c = #t terminate-alarm-ms : positive? = 200 read-stdout : (-> input-port? any/c) = read read-stderr : (-> input-port? any/c) = read