uni-channel
1 Model
2 Constructor
make-uni-channel
3 Predicates and accessors
uni-channel?
uni-channel-kind
uni-channel-direction
4 Sending and receiving
uni-channel-put
uni-channel-send
uni-channel-get
uni-channel-recv
uni-channel-try-get
uni-channel-get-evt
uni-channel-put-evt
5 Closing
uni-channel-close
uni-channel-closed?
6 Transport errors
uni-channel-error-get
uni-channel-error-try-get
uni-channel-error-evt
7 Examples
7.1 Async channel
7.2 Place channel pair
7.3 Port-channel endpoints over a pipe
9.2

uni-channel🔗ℹ

Hans Dijkema <hans@dijkewijk.nl>

 (require uni-channel) package: uni-channel

The uni-channel module provides one small wrapper around three Racket channel-like transports: async-channel?, place-channel? and port-channel?.

The constructor is deliberately simple:

(make-uni-channel channel)

The wrapper detects the concrete channel kind and exposes the same small set of operations for sending, receiving, event synchronization and closing. The wrapper does not change the transport semantics of the underlying channel. A place-channel? still accepts only place messages, and a port-channel? still transports serialized values as defined by port-channel.

1 Model🔗ℹ

A uni-channel has a kind and a direction.

The kind is one of:

The direction is one of:

  • 'bidirectional for async-channel and place-channel wrappers.

  • 'input or 'output for port-channel wrappers, copied from port-channel-direction.

A uni-channel that supports receiving is itself a synchronizable event. Synchronizing the wrapper returns the value received from the underlying channel:

(sync ch)

For output-only channels, synchronizing on the uni-channel uses never-evt. Such a channel has no receive side, so it can never become ready as a receive event.

2 Constructor🔗ℹ

procedure

(make-uni-channel channel)  uni-channel?

  channel : (or/c async-channel? place-channel? port-channel?)
Wraps channel as a uni-channel. The kind and direction are inferred from the supplied channel.

For async-channel? and place-channel?, the result is 'bidirectional. For port-channel?, the result has the same direction as the port-channel endpoint. To represent a full-duplex port-based connection, create one input port-channel? and one output port-channel?, then wrap each endpoint separately with make-uni-channel.

3 Predicates and accessors🔗ℹ

procedure

(uni-channel? v)  boolean?

  v : any/c
Returns true when v is a uni-channel.

procedure

(uni-channel-kind ch)  (or/c 'async 'place 'port)

  ch : uni-channel?
Returns the detected backend kind.

procedure

(uni-channel-direction ch)

  (or/c 'input 'output 'bidirectional)
  ch : uni-channel?
Returns the direction of ch.

4 Sending and receiving🔗ℹ

procedure

(uni-channel-put ch v)  void?

  ch : uni-channel?
  v : any/c
Sends v on ch. The channel must support output. For 'port channels, the value must be serializable by racket/serialize. For 'place channels, the value must be allowed as a place message.

procedure

(uni-channel-send ch v)  void?

  ch : uni-channel?
  v : any/c
Alias for uni-channel-put.

procedure

(uni-channel-get ch)  any/c

  ch : uni-channel?
Receives the next value from ch. The channel must support input.

procedure

(uni-channel-recv ch)  any/c

  ch : uni-channel?
Alias for uni-channel-get.

procedure

(uni-channel-try-get ch)  any/c

  ch : uni-channel?
Attempts to receive a value without blocking. Returns #f when no value is currently available. As with the underlying Racket operations, a queued #f value cannot be distinguished from no value by this function.

procedure

(uni-channel-get-evt ch)  evt?

  ch : uni-channel?
Returns a synchronizable receive event. Synchronizing this event returns the value received from the underlying channel. For output-only channels this returns never-evt, because no value can be received from that endpoint.

procedure

(uni-channel-put-evt ch v)  evt?

  ch : uni-channel?
  v : any/c
Returns an event that sends v when selected. The channel must support output.

5 Closing🔗ℹ

procedure

(uni-channel-close ch)  void?

  ch : uni-channel?
Closes the uni-channel wrapper. For async-channel and place-channel wrappers this marks only the wrapper as closed, because those Racket channel types do not have a native close operation. For port-channel wrappers this delegates to close-port-channel. Calling uni-channel-close more than once is safe.

procedure

(uni-channel-closed? ch)  boolean?

  ch : uni-channel?
Returns true when uni-channel-close has been called on ch.

6 Transport errors🔗ℹ

procedure

(uni-channel-error-get ch)  any/c

  ch : uni-channel?
Blocks until a transport error is available. Some wrapped transports can report asynchronous transport errors, for example I/O or serialization errors. Wrappers that do not have an error stream raise an exception.

procedure

(uni-channel-error-try-get ch)  any/c

  ch : uni-channel?
Attempts to get a transport error without blocking. Returns #f when no error is available. Wrappers that do not have an error stream also return #f.

procedure

(uni-channel-error-evt ch)  evt?

  ch : uni-channel?
Returns a synchronizable transport-error event. Wrappers that do not have an error stream return never-evt.

7 Examples🔗ℹ

7.1 Async channel🔗ℹ

(require racket/async-channel
         uni-channel)
 
(define ch (make-uni-channel (make-async-channel)))
 
(uni-channel-send ch 'hello)
(uni-channel-recv ch)

7.2 Place channel pair🔗ℹ

(require racket/place
         uni-channel)
 
(define-values (raw-a raw-b) (place-channel))
(define a (make-uni-channel raw-a))
(define b (make-uni-channel raw-b))
 
(uni-channel-send a '(hello from a))
(uni-channel-recv b)

7.3 Port-channel endpoints over a pipe🔗ℹ

(require port-channel
         uni-channel)
 
(define-values (in out) (make-pipe))
(define reader (make-uni-channel (make-port-channel in)))
(define writer (make-uni-channel (make-port-channel out)))
 
(uni-channel-send writer '(hello 1 2 3))
(uni-channel-recv reader)