The alt statement transfers control to one of several groups of statements depending on the readiness of communication channels. Its syntax resembles that of case:
labelopt alt { qual-statement-sequence }
outchan := chan of string;
inchan := chan of int;
alt {
i := <-inchan =>
sys->print("Received %d\n", i);
outchan <- = "message" =>
sys->print("Sent the message\n");
}
If a qualifier of the form * is present, then the statement does not block; if no channel is ready the statements associated with * are executed.
If two communication operators are present in the same qualifier expression, only the leftmost one is tested by alt. If two or more alt statements referring to the same receive (or send) channel are executed in different threads, the requests are queued; when the channel becomes unblocked, the thread that executed alt first is activated.
As with case, each qualifier and the statements following it up to the next qualifier together form a separate separate scope, like a block; declarations within this scope disappear at the next qualifier (or at the end of the statement.) Thus, in the example above, the scope of i in the arm
i := <-inchan =>
sys->print("Received %d\n", i);
As mentioned in the specification of the channel receive operator <- in §8.2.7, that operator can take an array of channels as an argument. This notation serves as a kind of simplified alt in which all the channels have the same type and are treated similarly. In this variant, the value of the communication expression is a tuple containing the index of the channel over which a communication was received and the value received. For example, in
a: array [2] of chan of string; a[0] = chan of string; a[1] = chan of string; . . . (i, s) := <- a; # s has now has the string from channel a[i]
During execution of an alt, the expressions in the qualifiers are evaluated in an undefined order, and in particular subexpressions may be evaluated before the channels are tested for readiness. Therefore qualifying expressions should not invoke side effects, and should avoid subparts that might delay execution. For example, in the qualifiers
ch <- = getchar() => # Bad idea ich <- = next++ => # Bad idea