Sending messages from task to task is central to any nontrivial coNCePTuaL program. Consequently, the language makes it exceptionally easy to send messages, as demonstrated by the following example:
As expected, the preceding line of code—itself a complete program that can be compiled and run—instructs the task with task number 0 to send a message to the task with task number 1. More subtly, it also instructs task 1 to receive a message sent to it by task 0. All other tasks (if any) do nothing. If the program is run with a single task, task will also quietly do nothing. In some communication libraries, sending to a nonexistent task hangs or crashes the program; in coNCePTuaL it's perfectly safe to send a message to a nonexistent task.
Messages don't have to be sent individually. A single statement can specify multiple senders and/or multiple receivers. The following statement causes the middle task to send a message to each other task in turn:
num_tasks
is a predefined variable set equal to the
total number of tasks in the program. num_tasks/2
refers
to half that number (i.e., the middle task).
coNCePTuaL provides a rich set of operators for specifying tasks. In the following code, each task with an odd task number sends a message to every fourth task. For example, in a 10-task run, tasks 1, 3, 5, 7, and 9 would each send to each of tasks 0, 4, and 8 for a total of 15 separate messages.
All of the code examples in the previous section utilize the default messaging attributes:
We now examine how to alter each attribute in turn.
The following code uses a different message buffer every time it executes:
The following code explicitly specifies a buffer (#7) and uses that even if other buffers are idle:
The following ensures that the send and receive message buffers lie at a memory location whose address is divisible by 128 (0, 128, 256, 384, …):
The following ensures that the send and receive message buffers lie at a memory location whose address is 128 bytes past a page boundary. Assuming that the operating system uses 4096-byte pages, the buffers can therefore lie at one of addresses 0, 4224, 8320, 12416, ….
Messages in coNCePTuaL are opaque. It
is not possible for a program to examine message contents. However,
two message attributes enable particular operations to be performed on
message data. The following code instructs the sender to
touch (read and write) every word of the message before
sending it and the receiver to touch every word of the message after
receiving it. The goal is to ensure that the messages are warm
in the cache, which may be a more realistic modus operandi than
communicating data that is never used.
Alteratively, coNCePTuaL can check message contents for bit errors. The implementation actually examines every bit of the message and can therefore detect errors that slip by a checksum or CRC calculation:
The predefined bit_errors
variable stores the number
of incorrect bits detected by the receiver when receiving a message
sent with verification.
Although we presented each message attribute individually, combinations are of course possible. The following code specifies all attributes at once just to prove that doing so is valid:
Let's review what we learned on this page: