The ccli iproc.ccl library provides three functions and some behind the scenes functionality that allow programs to send messages to each other (or to themselves) via ``mailboxes''. The library keeps a list of such mailboxes internally -- in reality they are queues of messages -- and associates an integer id to each one. Messages have type
[ to := int, from := int, ... ]where the to field defines what mailbox the message is to be sent to or what mailbox the message was received from. The from field is used to indicate what ``agent'' the message was sent from. Typically, each program in a composition of programs is associated with an id that it uses in the from field when it sends messages and that it expects in the to field when it receives them. Additional fields, defining the message content, may be included in messages. The iproc.ccl functions are:
external unit send ( [ to := int, from := int, ... ] )
This function is used to add
(enqueue) a message to the end of the mailbox (queue) associated with the integer identifier to.
external [ to := int, from := int, ... ] recv ( int )
This function is used to remove
(dequeue) a message from the mailbox (queue) associated with the integer identifier to. If
that mailbox is empty, a message with the from field equal to -1 is returned. The call
is non-blocking.
external bool inbox ( int )
This function is used to check whether the mailbox associated
with its integer argument has any messages in it. If it does, true is returned, otherwise false is returned.
Two considerations need to be taken into account when using the iproc.ccl library. First, be careful that your programs do not send significantly more messages to a mailbox than will be received from that mailbox. If a program keeps sending messages without receiving them, it will use up all the available memory on the system. The iproc.ccl helps you be careful about this by issuing annoying warnings every time a message is sent to a mailbox with more than some maximum number of messages in it (100 in the last distribution). Second, ccli can not type check messages sent with the library. That is, one program might send a message with a string field named msg. Another program may receive the message and then try to access a field named msg but use it with type int. Or it may try to access a field that was not defined in the message when it was sent. Both of these errors will not be caught by ccli at compile time and will issue runtime errors.
Here is an example to study. It defines agents numbered 0 to
. When agent
receives a
message from agent
, it sends a message to agent
. Agents 0 and
behave a little
differently. Note that the program prints out the messages in increasing order of agent id,
regardless of how the commands in the main composition are scheduled (try running it with and
without the -r option).
include iproc.ccl include standard.ccl include list.ccl program agent ( i, n ) := { got_mesg := if i = 0 then true else false end; sent_mesg := false; got_mesg & ! sent_mesg & i < n-1 : { send ( [ to := i+1, from := i, msg := "hi from " <> tostring ( i ) ] ), sent_mesg := true } inbox ( i ) & i != n-1 : { print ( recv ( i ), "\n" ), got_mesg := true } inbox ( i ) & i = n-1 : { print ( recv ( i ), "\n" ), exit() } }; program main() := compose i in range 10 : agent ( i, n );