3 -- Grant of Unlimited Rights
5 -- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687,
6 -- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained
7 -- unlimited rights in the software and documentation contained herein.
8 -- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making
9 -- this public release, the Government intends to confer upon all
10 -- recipients unlimited rights equal to those held by the Government.
11 -- These rights include rights to use, duplicate, release or disclose the
12 -- released technical data and computer software in whole or in part, in
13 -- any manner and for any purpose whatsoever, and to have or permit others
18 -- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR
19 -- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED
20 -- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE
21 -- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE
22 -- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A
23 -- PARTICULAR PURPOSE OF SAID MATERIAL.
27 -- Check that when a requeue is to the same entry the items go to the
28 -- right queue and that they are placed back on the end of the queue.
31 -- Simulate part of a message handling application where the messages are
32 -- composed of several segments. The sequence of the segments within the
33 -- message is specified by Seg_Sequence_No. The segments are handled by
34 -- different tasks and finally forwarded to an output driver. The
35 -- segments can arrive in any order but must be assembled into the proper
36 -- sequence for final output. There is a Sequencer task interposed
37 -- before the Driver. This takes the segments of the message off the
38 -- Ordering_Queue and those that are in the right order it sends on to
39 -- the driver; those that are out of order it places back on the end of
42 -- The test just simulates the arrival of the segments at the Sequencer.
43 -- The task generating the segments handshakes with the Sequencer during
44 -- the "Await Arrival" phase ensuring that the three segments of a
45 -- message arrive in REVERSE order (the End-of-Message segment arrives
46 -- first and the Header last). In the first cycle the sequencer pulls
47 -- segments off the queue and puts them back on the end till it
48 -- encounters the header. It checks the sequence of the ones it pulls
49 -- off in case the segments are being put back on in the wrong part of
50 -- the queue. Having cycled once through it no longer verifies the
51 -- sequence - it just executes the "application" code for the correct
52 -- order for dispatch to the driver.
54 -- In this simple example no attempt is made to address segments of
55 -- another message arriving or any other error conditions (such as
56 -- missing segments, timing etc.)
60 -- 06 Dec 94 SAIC ACVC 2.0
61 -- 19 Dec 94 SAIC Remove parameter from requeue statement
72 Report
.Test
("C954019", "Check Requeue to the same Accept");
74 declare -- encapsulate the test
76 type Segment_Sequence
is range 1..8;
77 Header
: constant Segment_Sequence
:= Segment_Sequence
'first;
79 type Message_Segment
is record
80 ID
: integer; -- Message ID
81 Seg_Sequence_No
: Segment_Sequence
; -- Within the message
82 Alpha
: string (1..128);
83 EOM
: Boolean := false; -- true for final msg segment
85 type acc_Message_Segment
is access Message_Segment
;
87 task TC_Simulate_Arrival
;
89 task type Carrier_Task
is
90 entry Input
( Segment
: acc_Message_Segment
);
92 type acc_Carrier_Task
is access Carrier_Task
;
95 entry Ordering_Queue
( Segment
: acc_Message_Segment
);
100 task Output_Driver
is
101 entry Input
( Segment
: acc_Message_Segment
);
105 -- Simulate the arrival of three message segments in REVERSE order
107 task body TC_Simulate_Arrival
is
112 -- Create a task for the next message segment
113 Next_Segment_Task
: acc_Carrier_Task
:= new Carrier_Task
;
114 -- Create a record for the next segment
115 Next_Segment
: acc_Message_Segment
:= new Message_Segment
;
118 -- Build the EOM segment as the first to "send"
119 Next_Segment
.Seg_Sequence_No
:= Header
+ 2;
120 Next_Segment
.EOM
:= true;
122 -- Wait for the first segment to arrive at the Sequencer
123 -- before "sending" the second
124 Sequencer
.TC_Handshake_1
;
126 Next_Segment
.Seg_Sequence_No
:= Header
+ 1;
128 -- Wait for the second segment to arrive at the Sequencer
129 -- before "sending" the third
130 Sequencer
.TC_Handshake_2
;
131 -- Build the segment. The last segment in order to
132 -- arrive will be the "header" segment
133 Next_Segment
.Seg_Sequence_No
:= Header
;
135 -- pass the record to its carrier
136 Next_Segment_Task
.Input
( Next_Segment
);
141 Report
.Failed
("Unexpected Exception in TC_Simulate_Arrival");
142 end TC_Simulate_Arrival
;
145 -- One of these is generated for each message segment and the flow
146 -- of the segments through the system is controlled by the calls the
147 -- task makes and the requeues of those calls
149 task body Carrier_Task
is
150 This_Segment
: acc_Message_Segment
:= new Message_Segment
;
152 accept Input
( Segment
: acc_Message_Segment
) do
153 This_Segment
.all := Segment
.all;
155 null; --:: stub. Pass the segment around the application as needed
157 -- Now output the segment to the Output_Driver. First we have to
158 -- go through the Sequencer.
159 Sequencer
.Ordering_Queue
( This_Segment
);
162 Report
.Failed
("Unexpected Exception in Carrier_Task");
166 -- Pull segments off the Ordering_Queue and deliver them in the correct
167 -- sequence to the Output_Driver.
169 task body Sequencer
is
170 Next_Needed
: Segment_Sequence
:= Header
;
172 TC_Await_Arrival
: Boolean := true;
173 TC_First_Cycle
: Boolean := true;
174 TC_Expected_Sequence
: Segment_Sequence
:= Header
+2;
178 accept Ordering_Queue
( Segment
: acc_Message_Segment
) do
180 --=====================================================
181 -- This part is all Test_Control code
183 if TC_Await_Arrival
then
184 -- We have to arrange that the segments arrive on the
185 -- queue in the right order, so we handshake with the
186 -- TC_Simulate_Arrival task to "send" only one at
188 accept TC_Handshake_1
; -- the first has arrived
189 -- and has been pulled off the
192 -- Wait for the second to arrive (the first has already
193 -- been pulled off the queue
194 while Ordering_Queue
'count < 1 loop
195 delay ImpDef
.Minimum_Task_Switch
;
198 accept TC_Handshake_2
; -- the second has arrived
200 -- Wait for the third to arrive
201 while Ordering_Queue
'count < 2 loop
202 delay ImpDef
.Minimum_Task_Switch
;
205 -- Subsequent passes through the loop, bypass this code
206 TC_Await_Arrival
:= false;
209 end if; -- await arrival
211 if TC_First_Cycle
then
212 -- Check the order of the original three
213 if Segment
.Seg_Sequence_No
/= TC_Expected_Sequence
then
214 -- The segments are not being pulled off in the
215 -- expected sequence. This could occur if the
216 -- requeue is not putting them back on the end.
217 Report
.Failed
("Sequencer: Segment out of sequence");
218 end if; -- sequence check
219 -- Decrement the expected sequence
220 if TC_Expected_Sequence
/= Header
then
221 TC_Expected_Sequence
:= TC_Expected_Sequence
- 1;
223 TC_First_Cycle
:= false; -- This is the Header - the
224 -- first two segments are
227 end if; -- decrementing
228 end if; -- first pass
229 --=====================================================
231 -- And this is the Application code
232 if Segment
.Seg_Sequence_No
= Next_Needed
then
234 Next_Needed
:= Header
; -- reset for next message
236 Next_Needed
:= Next_Needed
+ 1;
238 requeue Output_Driver
.Input
with abort;
239 Report
.Failed
("Requeue did not complete accept body");
241 -- Not the next needed - put it back on the queue
242 requeue Sequencer
.Ordering_Queue
;
243 Report
.Failed
("Requeue did not complete accept body");
252 Report
.Failed
("Unexpected Exception in Sequencer");
256 task body Output_Driver
is
257 This_Segment
: acc_Message_Segment
:= new Message_Segment
;
259 TC_Expected_Sequence
: Segment_Sequence
:= Segment_Sequence
'first;
260 TC_Segment_Total
: integer := 0;
261 TC_Expected_Total
: integer := 3;
264 -- Note: normally we would expect this Accept to be in a select
265 -- with terminate. For the test we exit the loop on completion
266 -- to give better control
267 accept Input
( Segment
: acc_Message_Segment
) do
268 This_Segment
.all := Segment
.all;
271 null; --::: stub - output the next segment of the message
273 -- The following is all test control code
275 if This_Segment
.Seg_Sequence_No
/= TC_Expected_Sequence
then
276 Report
.Failed
("Output_Driver: Segment out of sequence");
278 TC_Expected_Sequence
:= TC_Expected_Sequence
+ 1;
280 -- Now count the number of segments
281 TC_Segment_Total
:= TC_Segment_Total
+ 1;
283 -- Check the number and exit loop when complete
284 -- There must be exactly TC_Expected_Total in number and
285 -- the last one must be EOM
286 -- (test will hang if < TC_Expected_Total arrive
288 if This_Segment
.EOM
then
289 -- This is the last segment.
290 if TC_Segment_Total
/= TC_Expected_Total
then
291 Report
.Failed
("EOM and wrong number of segments");
293 exit; -- the loop and terminate the task
294 elsif TC_Segment_Total
= TC_Expected_Total
then
295 Report
.Failed
("No EOM found");
301 Report
.Failed
("Unexpected Exception in Output_Driver");
310 end; -- encapsulation