Creating a Channel
A communication channel can be created between two processes to allow them to communicate. Channel creation is done using the channel
keyword. Here's an example of channel declaration:
channel p1.out (string, int)> p2.in;
In this example, a channel named out
is created on process p1
to send messages of type (string, int)
to the channel named in
on process p2
. Messages must strictly have the declared type. For now, channels can only be used in one direction (from p1
to p2
, indicated by the >
chevron).
The self
keyword refers to the current process and can be used to create a channel with another process.
channel self.out (string, int)> p2.in;
Sending Messages
A message is sent on a channel using the send
instruction. Here's an example of sending a message:
program Prog1() {
send out("Hello", 42);
}
In this example, the message (Hello, 42)
is sent on the out
channel of the current process. For this instruction to be valid, a program must have declared an out
channel on at least one process of type Prog1
. This ensures that message types are consistent.
Thus, for the previous example to work, the out
channel declaration must be attached to a program of type Prog1
:
The complete code is as follows:
main {
let p1 = run Prog1();
channel p1.out (string, int)> self.in;
}
program Prog1() {
send out("Hello", 42);
}
Since compilation occurs from top to bottom, it is necessary to declare channels before using them to ensure correct type checking. However, the main
program is always compiled first, so it is possible to move the main
program declaration to the bottom of the file.
Sending a message is an asynchronous operation, meaning the process sending the message continues its execution without waiting for the recipient process to receive the message.
Receiving Messages
A message is received on a channel using the receive
instruction.
This is a particular operation that must be preceded by the wait
instruction to make it blocking.
Here's an example of message reception:
main {
let p1 = run Prog1();
channel p1.out (string, int)> self.in;
wait receive in (x, y) => {
print("Message received: ", x, y);
}
}
program Prog1() {
send out("Hello", 42);
}
We can see that the received values are stored in the variables x
and y
and can only be used in the instruction block following the receive
instruction.
The type of the variables is automatically deduced from the channel type.