Select in Ada

Ada’s select statement allows you to wait on multiple entry calls. Combining tasks and entries with select is a powerful feature of Ada.

with Ada.Text_IO;
with Ada.Calendar;

procedure Select_Example is
   use Ada.Text_IO;
   use Ada.Calendar;

   task type Channel is
      entry Send (Msg : String);
      entry Receive (Msg : out String);
   end Channel;

   task body Channel is
      Message : String (1 .. 10);
   begin
      select
         accept Send (Msg : String) do
            Message := Msg;
         end Send;
      or
         accept Receive (Msg : out String) do
            Msg := Message;
         end Receive;
      end select;
   end Channel;

   C1, C2 : Channel;

   procedure Sender (Ch : not null access Channel; Msg : String; Delay_Time : Duration) is
   begin
      delay Delay_Time;
      Ch.Send (Msg);
   end Sender;

begin
   -- For our example we'll select across two channels.

   -- Each channel will receive a value after some amount
   -- of time, to simulate e.g. blocking RPC operations
   -- executing in concurrent tasks.
   declare
      T1 : Time := Clock;
   begin
      Sender (C1'Access, "one      ", 1.0);
      Sender (C2'Access, "two      ", 2.0);

      -- We'll use `select` to await both of these values
      -- simultaneously, printing each one as it arrives.
      for I in 1 .. 2 loop
         select
            accept C1.Receive (Msg : out String) do
               Put_Line ("received " & Msg);
            end C1.Receive;
         or
            accept C2.Receive (Msg : out String) do
               Put_Line ("received " & Msg);
            end C2.Receive;
         end select;
      end loop;

      Put_Line ("Total time: " & Duration'Image (Clock - T1) & " seconds");
   end;
end Select_Example;

To run the program, save it as select_example.adb and use the following commands:

$ gnatmake select_example.adb
$ ./select_example
received one      
received two      
Total time:  2.000235000 seconds

We receive the values “one” and then “two” as expected.

Note that the total execution time is only ~2 seconds since both the 1 and 2 second delays execute concurrently.

In this Ada version, we use tasks instead of goroutines, and entries instead of channels. The select statement in Ada allows us to wait on multiple entry calls, similar to Go’s select statement waiting on multiple channel operations. The structure and behavior of the program remain similar to the original Go version, demonstrating Ada’s concurrent programming capabilities.