port-channel
| (require port-channel) | package: port-channel |
The port-channel module wraps a Racket port as an asynchronous, channel-like object. It is intended as a small building block for stream-based communication protocols, for example between a parent Racket process and a subprocess connected through standard input and standard output.
A port-channel transports serialized Racket values. The implementation uses racket/serialize: values are passed through serialize, written to the port, read back as Racket data and reconstructed with deserialize. Ordinary data values work directly. Custom structures must be defined with serializable-struct. Ports, threads, custodians and ordinary procedures are not serializable values.
1 Model
A port-channel has one of two directions:
'input: a reader thread reads complete serialized values from an input port and puts the deserialized values on an internal asynchronous channel. The port-channel is itself a synchronizable event, so (sync pc) returns the next complete value.
'output: port-channel-put queues values on an internal asynchronous channel. A writer thread serializes and writes queued values to the output port.
Buffered I/O alone is not enough to provide this behaviour. Synchronizing on a raw input port only says that some input is available; it does not guarantee that a complete serialized value is ready. The reader thread converts the byte stream into complete channel messages.
2 Reference
procedure
(make-port-channel port [ #:direction direction #:source source #:close? close?]) → port-channel? port : port? direction : (or/c 'auto 'input 'output) = 'auto source : any/c = 'port close? : any/c = #t
The source value is stored in reported port-channel-error values. When close? is true, close-port-channel closes the underlying port.
procedure
(port-channel? v) → boolean?
v : any/c
procedure
(port-channel-direction pc) → (or/c 'input 'output)
pc : port-channel?
procedure
(port-channel-put pc v) → void?
pc : port-channel? v : any/c
The value must be serializable by serialize. If serialization or writing fails, a port-channel-error is published on the error channel.
procedure
(port-channel-get pc) → any/c
pc : port-channel?
procedure
(port-channel-try-get pc) → any/c
pc : port-channel?
procedure
(port-channel-evt pc) → evt?
pc : port-channel?
procedure
(close-port-channel pc) → void?
pc : port-channel?
procedure
(port-channel-wait pc) → void?
pc : port-channel?
3 Errors
procedure
pc : port-channel?
procedure
(port-channel-error-try-get pc) → any/c
pc : port-channel?
procedure
(port-channel-error-evt pc) → evt?
pc : port-channel?
4 Example
(require port-channel) (define-values (in out) (make-pipe)) (define reader (make-port-channel in)) (define writer (make-port-channel out)) (port-channel-put writer '(hello 1 2 3)) (sync reader)
The result is:
'(hello 1 2 3)
5 Serializable structures
(require racket/serialize port-channel) (serializable-struct message (id payload) #:transparent) (define-values (in out) (make-pipe)) (define reader (make-port-channel in)) (define writer (make-port-channel out)) (port-channel-put writer (message 1 '(a b c))) (sync reader)
The received value is a reconstructed message structure.