of guards can have changed. Calls to entries can be requeued to other entries with the same signature. A task that is requeued is blocked and added to the queue of the target entry; this means that the protected object is released and allows admission of another task. The select statement in Ada can be used to implement non-blocking entry calls and accepts, non-deterministic selection of entries (also with guards), time-outs and aborts. The following example illustrates some concepts of concurrent programming in Ada. with Ada.Text_IO; use Ada.Text_IO; procedure Traffic is type Airplane_ID is range 1..10; -- 10 airplanes task type Airplane (ID: Airplane_ID); -- task representing airplanes, with ID as initialisation parameter type Airplane_Access is access Airplane; -- reference type to Airplane protected type Runway is -- the shared runway (protected to allow concurrent access) entry Assign_Aircraft (ID: Airplane_ID); -- all entries are guaranteed mutually exclusive entry Cleared_Runway (ID: Airplane_ID); entry Wait_For_Clear; private Clear: Boolean := True; -- protected private data - generally more than only a flag... end Runway; type Runway_Access is access all Runway; -- the air traffic controller task takes requests for takeoff and landing task type Controller (My_Runway: Runway_Access) is -- task entries for synchronous message passing entry Request_Takeoff (ID: in Airplane_ID; Takeoff: out Runway_Access); entry Request_Approach(ID: in Airplane_ID; Approach: out Runway_Access); end Controller; -- allocation of instances Runway1 : aliased Runway; -- instantiate a runway Controller1: Controller (Runway1'Access); -- and a controller to manage it ------ the implementations of the above types ------ protected body Runway is entry Assign_Aircraft (ID: Airplane_ID) when Clear is -- the entry guard - calling tasks are blocked until the condition is true begin Clear := False; Put_Line (Airplane_ID'Image (ID) & " on runway "); end; entry Cleared_Runway (ID: Airplane_ID) when not Clear is begin Clear := True; Put_Line (Airplane_ID'Image (ID) & " cleared runway "); end; entry Wait_For_Clear when Clear is begin null; -- no need to do anything here - a task can only enter if "Clear" is true end; end Runway; task body Controller is begin loop My_Runway.Wait_For_Clear; -- wait until runway is available (blocking call) select -- wait for two types of requests (whichever is runnable first) when Request_Approach'count = 0 => -- guard statement - only accept if there are no tasks queuing on Request_Approach accept Request_Takeoff (ID: in Airplane_ID; Takeoff: out Runway_Access) do -- start of synchronized part My_Runway.Assign_Aircraft (ID); -- reserve runway