1------------------------------------------------------------------------------
2--                                                                          --
3--                 GNAT RUN-TIME LIBRARY (GNARL) COMPONENTS                 --
4--                                                                          --
5--           S Y S T E M . T A S K I N G . A S Y N C _ D E L A Y S          --
6--                                                                          --
7--                                  S p e c                                 --
8--                                                                          --
9--          Copyright (C) 1998-2020, Free Software Foundation, Inc.         --
10--                                                                          --
11-- GNARL is free software; you can  redistribute it  and/or modify it under --
12-- terms of the  GNU General Public License as published  by the Free Soft- --
13-- ware  Foundation;  either version 3,  or (at your option) any later ver- --
14-- sion.  GNAT is distributed in the hope that it will be useful, but WITH- --
15-- OUT ANY WARRANTY;  without even the  implied warranty of MERCHANTABILITY --
16-- or FITNESS FOR A PARTICULAR PURPOSE.                                     --
17--                                                                          --
18-- As a special exception under Section 7 of GPL version 3, you are granted --
19-- additional permissions described in the GCC Runtime Library Exception,   --
20-- version 3.1, as published by the Free Software Foundation.               --
21--                                                                          --
22-- You should have received a copy of the GNU General Public License and    --
23-- a copy of the GCC Runtime Library Exception along with this program;     --
24-- see the files COPYING3 and COPYING.RUNTIME respectively.  If not, see    --
25-- <http://www.gnu.org/licenses/>.                                          --
26--                                                                          --
27-- GNARL was developed by the GNARL team at Florida State University.       --
28-- Extensive contributions were provided by Ada Core Technologies, Inc.     --
29--                                                                          --
30------------------------------------------------------------------------------
31
32--  This package contains the procedures to implements timeouts (delays) for
33--  asynchronous select statements.
34
35--  Note: the compiler generates direct calls to this interface, via Rtsfind.
36--  Any changes to this interface may require corresponding compiler changes.
37
38package System.Tasking.Async_Delays is
39
40   --  Suppose the following source code is given:
41
42   --  select delay When;
43   --     ...continuation for timeout case...
44   --  then abort
45   --     ...abortable part...
46   --  end select;
47
48   --  The compiler should expand this to the following:
49
50   --  declare
51   --     DB : aliased Delay_Block;
52   --  begin
53   --     if System.Tasking.Async_Delays.Enqueue_Duration
54   --       (When, DB'Unchecked_Access)
55   --     then
56   --        begin
57   --           A101b : declare
58   --              procedure _clean is
59   --              begin
60   --                 System.Tasking.Async_Delays.Cancel_Async_Delay
61   --                   (DB'Unchecked_Access);
62   --                 return;
63   --              end _clean;
64   --           begin
65   --              abort_undefer.all;
66   --              ...abortable part...
67   --           exception
68   --              when all others =>
69   --                 declare
70   --                    E105b : exception_occurrence;
71   --                 begin
72   --                    save_occurrence (E105b, get_current_excep.all.all);
73   --                    _clean;
74   --                    reraise_occurrence_no_defer (E105b);
75   --                 end;
76   --           at end
77   --              _clean;
78   --           end A101b;
79   --        exception
80   --           when _abort_signal =>
81   --              abort_undefer.all;
82   --        end;
83   --     end if;
84
85   --     if Timed_Out (DB'Unchecked_Access) then
86   --        ...continuation for timeout case...
87   --     end if;
88   --  end;
89
90   -----------------
91   -- Delay_Block --
92   -----------------
93
94   type Delay_Block is limited private;
95   type Delay_Block_Access is access all Delay_Block;
96
97   function Enqueue_Duration
98     (T : Duration;
99      D : Delay_Block_Access) return Boolean;
100   --  Enqueue the specified relative delay. Returns True if the delay has
101   --  been enqueued, False if it has already expired. If the delay has been
102   --  enqueued, abort is deferred.
103
104   procedure Cancel_Async_Delay (D : Delay_Block_Access);
105   --  Cancel the specified asynchronous delay
106
107   function Timed_Out (D : Delay_Block_Access) return Boolean;
108   pragma Inline (Timed_Out);
109   --  Return True if the delay specified in D has timed out
110
111   --  There are child units for delays on Ada.Calendar.Time/Ada.Real_Time.Time
112   --  so that an application need not link in features that it is not using.
113
114private
115
116   type Delay_Block is limited record
117      Self_Id : Task_Id;
118      --  ID of the calling task
119
120      Level : ATC_Level_Base;
121      --  Normally Level is the ATC nesting level of the asynchronous select
122      --  statement to which this delay belongs, but after a call has been
123      --  dequeued we set it to Level_No_Pending_Abort so that the Cancel
124      --  operation can detect repeated calls, and act idempotently.
125
126      Resume_Time : Duration;
127      --  The absolute wake up time, represented as Duration
128
129      Timed_Out : Boolean := False;
130      --  Set to true if the delay has timed out
131
132      Succ, Pred : Delay_Block_Access;
133      --  A double linked list
134   end record;
135
136   --  The above "overlaying" of Self_Id and Level to hold other data that has
137   --  a non-overlapping lifetime is an unabashed hack to save memory.
138
139   procedure Time_Enqueue
140     (T : Duration;
141      D : Delay_Block_Access);
142   pragma Inline (Time_Enqueue);
143   --  Used by the child units to enqueue delays on the timer queue implemented
144   --  in the body of this package. T denotes a point in time as the duration
145   --  elapsed since the epoch of the Ada real-time clock.
146
147end System.Tasking.Async_Delays;
148