Place Controllers
1 Example
2 Reference
place-controller/  c
make-place-controller/  dynamic-place*

Place Controllers

Sage Gerard

 (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.

1 Example


#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))
                  (place-channel-put pch "omg someone said hi to me")]
        [else (displayln "Huh?")


#lang racket/base
(require racket/runtime-path
(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 ($))

2 Reference


place-controller/c : 
(case-> (-> evt?)
        (-> any/c evt?))
A contract that represents a place controller.

A place controller is a procedure that returns a synchronizable event, where the event’s synchronization result is an instance of a place-datum-envelope subtype or a place-detach-envelope subtype.

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
  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?)
A structure representing an identifiable place controller and all resources it manages. controller is a reference to the place controller procedure, and all other fields are references to the same arguments in a corresponding call to make-place-controller.

place-resources implements prop:procedure. When an instance is called as a procedure, the call forwards to the controller.

Possible synchronization results of an event returned by a place controller while the place is actively producing values.

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.


(struct place-detach-envelope (resources))

  resources : place-resources?


(struct detach-clean place-detach-envelope (completion-value))

  completion-value : exact-integer?


(struct detach-dirty place-detach-envelope ())

Possible synchronization results of an event returned by a place controller, once the controller has stopped interacting with the place.

detach-dirty indicates that the place controller did not free the given resources.

detach-clean indicates that the place controller did free the resources, and the place stopped with the given completion-value.


  [#: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]) 
  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
Returns a procedure P that manages the lifecycle of the place pch. P assumes that source-stdout corresponds to the place’s current-output-port, source-stderr corresponds to the place’s current-error-port, and sink-stdin corresponds to the place’s current-input-port.

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.

The id does not have any impact on the controller’s behavior. It is merely made available in an instance of place-resources accessible from a synchronization result.

If P is applied to a value, it has a side-effect before returning a synchronizable event:

Note that the default value for read-stdout and read-stderr is read. This means that if a place wants to transport a string, it must do so using write.

P reads individual values from source-stdout and source-stderr, using read-stdout or read-stderr. The place may need to use flush-output to unblock P.

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.


  #:id id 
  #:clean-up? clean-up? 
  #:terminate-alarm-ms terminate-alarm-ms 
  #:read-stdout read-stdout 
  #:read-stderr read-stderr]) 
  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
Like dynamic-place*, except the resulting place always uses new OS-level ports. Returns a place controller to manage the created place.

module-path and start-name mean the same as they do for dynamic-place*. All other arguments mean the same as they do for make-place-controller.