David K. Storrs
Provides a single-threaded message loop that can be used as an aggregation point to trigger arbitrary actions. Essentially a thread that listens on an async channel, sends the result through a dispatch table, and then loops.
The message loop can be started before or after listeners are added. When a message is posted, all listeners who have registered for that type of message will have a chance to react, in an unspecified order.
> (struct++person(nameage)#:transparent);Listen for 'birth messages and send out a nicely formatted string#:id'listener1(async-channel-putch(message-typemsg)(person-namep))))));listener notices that bob was born, puts that fact on the channel"listener listener1, message 'birth. Bob was born"
;Add multiple listeners at once, one for 'birthday messages and one for 'birthday-modify messages#:id'listener2(async-channel-putch(person.namep)1234))))#:id'listener3#:commcomm-chmsg)(async-channel-put(rx-tx-async-channel.to-parent(set-person-ageprsnnew-age))))#:id'type-only-listener;post a birthday for bob, get back a string describing it"listener listener2 heard that Bob had a birthday at time 1234"
;post a birthday-modify for bob, get back an updated version of bob(person "Bob" 18)
;post a birthday for Alice to demonstrate that the listener didn't stop after running once"listener listener2 heard that Alice had a birthday at time 1234"
;ditto for birthday-modify(person "Alice" 25)
;post a message type. the message struct will be created#<message>
;multiple listeners can trigger from a single message#:id'listener-X(async-channel-putch#:id'listener-Y(async-channel-putch;We will get back the IDs of the listeners that receive the message'(listener-X listener-Y)
;One listener that listens for both 'matriculate and 'graduate messages#:id'multiple-type-listener(async-channel-putch(message-typemsg)(person.namep))))));Receive a 'matriculate message"listener multiple-type-listener, message type 'matriculate for Bob"
;Receive a 'graduate message"listener multiple-type-listener, message type 'graduate for Bob"
procedure
procedure
( stop-message-loop )→any
The message structure is used to signal that interested listeners should activate.
procedure
[ #:sourcesource#:datadata]) → message?type:message-type?
procedure
( message.type msg)→message-type?
msg:message?msg:message?msg:message?
procedure
( post-message msg)→any
msg:message?
The listener structure defines what message types to listen for and what to do with them.
procedure
#:actionaction[ #:idid#:commcomm]) → listener?comm:rx-tx-async-channel?=(rx-tx-async-channel++)
listen-for is a list of message types to listen for. NOTE: As a convenience, you may specify a single message type and it will be converted to a one-element list in the process of creating the struct.
action is the procedure that will be called when the relevant message type comes in. It is called with the listener itself and with the message that triggered the listener.
id allows you to easily distinguish between listeners.
comm provides a pair of async channels that can be used to communicate to and from the listener.
procedure
( listener.listen-for l)→(listof message-type?)
l:listener?l:listener?l:listener?l:listener?
procedure
( add-listener l)→any
l:listener?
procedure
( add-listeners l...)→any
l:listener?