OSDN Git Service

PR ada/53766
[pf3gnuchains/gcc-fork.git] / gcc / ada / a-cuprqu.adb
1 ------------------------------------------------------------------------------
2 --                                                                          --
3 --                         GNAT LIBRARY COMPONENTS                          --
4 --                                                                          --
5 --                 ADA.CONTAINERS.UNBOUNDED_PRIORITY_QUEUES                 --
6 --                                                                          --
7 --                                 B o d y                                  --
8 --                                                                          --
9 --            Copyright (C) 2011, Free Software Foundation, Inc.            --
10 --                                                                          --
11 -- GNAT 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 -- This unit was originally developed by Matthew J Heaney.                  --
28 ------------------------------------------------------------------------------
29
30 with Ada.Unchecked_Deallocation;
31
32 package body Ada.Containers.Unbounded_Priority_Queues is
33
34    package body Implementation is
35
36       -----------------------
37       -- Local Subprograms --
38       -----------------------
39
40       procedure Free is
41          new Ada.Unchecked_Deallocation (Node_Type, Node_Access);
42
43       -------------
44       -- Dequeue --
45       -------------
46
47       procedure Dequeue
48         (List    : in out List_Type;
49          Element : out Queue_Interfaces.Element_Type)
50       is
51          X : Node_Access;
52
53       begin
54          Element := List.First.Element;
55
56          X := List.First;
57          List.First := List.First.Next;
58
59          if List.First = null then
60             List.Last := null;
61          end if;
62
63          List.Length := List.Length - 1;
64
65          Free (X);
66       end Dequeue;
67
68       procedure Dequeue
69         (List     : in out List_Type;
70          At_Least : Queue_Priority;
71          Element  : in out Queue_Interfaces.Element_Type;
72          Success  : out Boolean)
73       is
74       begin
75          --  This operation dequeues a high priority item if it exists in the
76          --  queue. By "high priority" we mean an item whose priority is equal
77          --  or greater than the value At_Least. The generic formal operation
78          --  Before has the meaning "has higher priority than". To dequeue an
79          --  item (meaning that we return True as our Success value), we need
80          --  as our predicate the equivalent of "has equal or higher priority
81          --  than", but we cannot say that directly, so we require some logical
82          --  gymnastics to make it so.
83
84          --  If E is the element at the head of the queue, and symbol ">"
85          --  refers to the "is higher priority than" function Before, then we
86          --  derive our predicate as follows:
87          --    original: P(E) >= At_Least
88          --    same as:  not (P(E) < At_Least)
89          --    same as:  not (At_Least > P(E))
90          --    same as:  not Before (At_Least, P(E))
91
92          --  But that predicate needs to be true in order to successfully
93          --  dequeue an item. If it's false, it means no item is dequeued, and
94          --  we return False as the Success value.
95
96          if List.Length = 0
97            or else Before (At_Least, Get_Priority (List.First.Element))
98          then
99             Success := False;
100             return;
101          end if;
102
103          List.Dequeue (Element);
104          Success := True;
105       end Dequeue;
106
107       -------------
108       -- Enqueue --
109       -------------
110
111       procedure Enqueue
112         (List     : in out List_Type;
113          New_Item : Queue_Interfaces.Element_Type)
114       is
115          P : constant Queue_Priority := Get_Priority (New_Item);
116
117          Node : Node_Access;
118          Prev : Node_Access;
119
120       begin
121          Node := new Node_Type'(New_Item, null);
122
123          if List.First = null then
124             List.First := Node;
125             List.Last := List.First;
126
127          else
128             Prev := List.First;
129
130             if Before (P, Get_Priority (Prev.Element)) then
131                Node.Next := List.First;
132                List.First := Node;
133
134             else
135                while Prev.Next /= null loop
136                   if Before (P, Get_Priority (Prev.Next.Element)) then
137                      Node.Next := Prev.Next;
138                      Prev.Next := Node;
139
140                      exit;
141                   end if;
142
143                   Prev := Prev.Next;
144                end loop;
145
146                if Prev.Next = null then
147                   List.Last.Next := Node;
148                   List.Last := Node;
149                end if;
150             end if;
151          end if;
152
153          List.Length := List.Length + 1;
154
155          if List.Length > List.Max_Length then
156             List.Max_Length := List.Length;
157          end if;
158       end Enqueue;
159
160       --------------
161       -- Finalize --
162       --------------
163
164       procedure Finalize (List : in out List_Type) is
165          X : Node_Access;
166       begin
167          while List.First /= null loop
168             X := List.First;
169             List.First := List.First.Next;
170             Free (X);
171          end loop;
172       end Finalize;
173
174       ------------
175       -- Length --
176       ------------
177
178       function Length (List : List_Type) return Count_Type is
179       begin
180          return List.Length;
181       end Length;
182
183       ----------------
184       -- Max_Length --
185       ----------------
186
187       function Max_Length (List : List_Type) return Count_Type is
188       begin
189          return List.Max_Length;
190       end Max_Length;
191
192    end Implementation;
193
194    protected body Queue is
195
196       -----------------
197       -- Current_Use --
198       -----------------
199
200       function Current_Use return Count_Type is
201       begin
202          return List.Length;
203       end Current_Use;
204
205       -------------
206       -- Dequeue --
207       -------------
208
209       entry Dequeue (Element : out Queue_Interfaces.Element_Type)
210         when List.Length > 0
211       is
212       begin
213          List.Dequeue (Element);
214       end Dequeue;
215
216       --------------------------------
217       -- Dequeue_Only_High_Priority --
218       --------------------------------
219
220       procedure Dequeue_Only_High_Priority
221         (At_Least : Queue_Priority;
222          Element  : in out Queue_Interfaces.Element_Type;
223          Success  : out Boolean)
224       is
225       begin
226          List.Dequeue (At_Least, Element, Success);
227       end Dequeue_Only_High_Priority;
228
229       -------------
230       -- Enqueue --
231       -------------
232
233       entry Enqueue (New_Item : Queue_Interfaces.Element_Type) when True is
234       begin
235          List.Enqueue (New_Item);
236       end Enqueue;
237
238       --------------
239       -- Peak_Use --
240       --------------
241
242       function Peak_Use return Count_Type is
243       begin
244          return List.Max_Length;
245       end Peak_Use;
246
247    end Queue;
248
249 end Ada.Containers.Unbounded_Priority_Queues;