| -- C980003.A |
| -- |
| -- Grant of Unlimited Rights |
| -- |
| -- Under contracts F33600-87-D-0337, F33600-84-D-0280, MDA903-79-C-0687, |
| -- F08630-91-C-0015, and DCA100-97-D-0025, the U.S. Government obtained |
| -- unlimited rights in the software and documentation contained herein. |
| -- Unlimited rights are defined in DFAR 252.227-7013(a)(19). By making |
| -- this public release, the Government intends to confer upon all |
| -- recipients unlimited rights equal to those held by the Government. |
| -- These rights include rights to use, duplicate, release or disclose the |
| -- released technical data and computer software in whole or in part, in |
| -- any manner and for any purpose whatsoever, and to have or permit others |
| -- to do so. |
| -- |
| -- DISCLAIMER |
| -- |
| -- ALL MATERIALS OR INFORMATION HEREIN RELEASED, MADE AVAILABLE OR |
| -- DISCLOSED ARE AS IS. THE GOVERNMENT MAKES NO EXPRESS OR IMPLIED |
| -- WARRANTY AS TO ANY MATTER WHATSOEVER, INCLUDING THE CONDITIONS OF THE |
| -- SOFTWARE, DOCUMENTATION OR OTHER INFORMATION RELEASED, MADE AVAILABLE |
| -- OR DISCLOSED, OR THE OWNERSHIP, MERCHANTABILITY, OR FITNESS FOR A |
| -- PARTICULAR PURPOSE OF SAID MATERIAL. |
| --* |
| -- |
| -- TEST OBJECTIVE: |
| -- Check that aborts are deferred during the execution of an |
| -- Initialize procedure (as the last step of the default |
| -- initialization of a controlled object), during the execution |
| -- of a Finalize procedure (as part of the finalization of a |
| -- controlled object), and during an assignment operation to an |
| -- object with a controlled part. |
| -- |
| -- TEST DESCRIPTION: |
| -- A controlled type is created with Initialize, Adjust, and |
| -- Finalize operations. These operations note in a protected |
| -- object when the operation starts and completes. This change |
| -- in state of the protected object will open the barrier for |
| -- the entry in the protected object. |
| -- The test contains declarations of objects of the controlled |
| -- type. An asynchronous select is used to attempt to abort |
| -- the operations on the controlled type. The asynchronous select |
| -- makes use of the state change to the protected object to |
| -- trigger the abort. |
| -- |
| -- |
| -- CHANGE HISTORY: |
| -- 11 Jan 96 SAIC Initial Release for 2.1 |
| -- 5 May 96 SAIC Incorporated Reviewer comments. |
| -- 10 Oct 96 SAIC Addressed issue where assignment statement |
| -- can be 2 assignment operations. |
| -- |
| --! |
| |
| with Ada.Finalization; |
| package C980003_0 is |
| Verbose : constant Boolean := False; |
| |
| -- the following flag is set true whenever the |
| -- Initialize operation is called. |
| Init_Occurred : Boolean; |
| |
| type Is_Controlled is new Ada.Finalization.Controlled with |
| record |
| Id : Integer; |
| end record; |
| |
| procedure Initialize (Object : in out Is_Controlled); |
| procedure Finalize (Object : in out Is_Controlled); |
| procedure Adjust (Object : in out Is_Controlled); |
| |
| type States is (Unknown, |
| Start_Init, Finished_Init, |
| Start_Adjust, Finished_Adjust, |
| Start_Final, Finished_Final); |
| |
| protected State_Manager is |
| procedure Reset; |
| procedure Set (New_State : States); |
| function Current return States; |
| entry Wait_For_Change; |
| private |
| Current_State : States := Unknown; |
| Changed : Boolean := False; |
| end State_Manager; |
| |
| end C980003_0; |
| |
| |
| with Report; |
| with ImpDef; |
| package body C980003_0 is |
| protected body State_Manager is |
| procedure Reset is |
| begin |
| Current_State := Unknown; |
| Changed := False; |
| end Reset; |
| |
| procedure Set (New_State : States) is |
| begin |
| Changed := True; |
| Current_State := New_State; |
| end Set; |
| |
| function Current return States is |
| begin |
| return Current_State; |
| end Current; |
| |
| entry Wait_For_Change when Changed is |
| begin |
| Changed := False; |
| end Wait_For_Change; |
| end State_Manager; |
| |
| procedure Initialize (Object : in out Is_Controlled) is |
| begin |
| if Verbose then |
| Report.Comment ("starting initialize"); |
| end if; |
| State_Manager.Set (Start_Init); |
| if Verbose then |
| Report.Comment ("in initialize"); |
| end if; |
| delay ImpDef.Switch_To_New_Task; -- tempting place for abort |
| State_Manager.Set (Finished_Init); |
| if Verbose then |
| Report.Comment ("finished initialize"); |
| end if; |
| Init_Occurred := True; |
| end Initialize; |
| |
| procedure Finalize (Object : in out Is_Controlled) is |
| begin |
| if Verbose then |
| Report.Comment ("starting finalize"); |
| end if; |
| State_Manager.Set (Start_Final); |
| if Verbose then |
| Report.Comment ("in finalize"); |
| end if; |
| delay ImpDef.Switch_To_New_Task; -- tempting place for abort |
| State_Manager.Set (Finished_Final); |
| if Verbose then |
| Report.Comment ("finished finalize"); |
| end if; |
| end Finalize; |
| |
| procedure Adjust (Object : in out Is_Controlled) is |
| begin |
| if Verbose then |
| Report.Comment ("starting adjust"); |
| end if; |
| State_Manager.Set (Start_Adjust); |
| if Verbose then |
| Report.Comment ("in adjust"); |
| end if; |
| delay ImpDef.Switch_To_New_Task; -- tempting place for abort |
| State_Manager.Set (Finished_Adjust); |
| if Verbose then |
| Report.Comment ("finished adjust"); |
| end if; |
| end Adjust; |
| end C980003_0; |
| |
| |
| with Report; |
| with ImpDef; |
| with C980003_0; use C980003_0; |
| with Ada.Unchecked_Deallocation; |
| procedure C980003 is |
| |
| procedure Check_State (Should_Be : States; |
| Msg : String) is |
| Cur : States := State_Manager.Current; |
| begin |
| if Cur /= Should_Be then |
| Report.Failed (Msg); |
| Report.Comment ("expected: " & States'Image (Should_Be) & |
| " found: " & States'Image (Cur)); |
| elsif Verbose then |
| Report.Comment ("passed: " & Msg); |
| end if; |
| end Check_State; |
| |
| begin |
| |
| Report.Test ("C980003", "Check that aborts are deferred during" & |
| " initialization, finalization, and assignment" & |
| " operations on controlled objects"); |
| |
| Check_State (Unknown, "initial condition"); |
| |
| -- check that initialization and finalization take place |
| Init_Occurred := False; |
| select |
| State_Manager.Wait_For_Change; |
| then abort |
| declare |
| My_Controlled_Obj : Is_Controlled; |
| begin |
| delay 0.0; -- abort completion point |
| Report.Failed ("state change did not occur"); |
| end; |
| end select; |
| if not Init_Occurred then |
| Report.Failed ("Initialize did not complete"); |
| end if; |
| Check_State (Finished_Final, "init/final for declared item"); |
| |
| -- check adjust |
| State_Manager.Reset; |
| declare |
| Source, Dest : Is_Controlled; |
| begin |
| Check_State (Finished_Init, "adjust initial state"); |
| Source.Id := 3; |
| Dest.Id := 4; |
| State_Manager.Reset; -- so we will wait for change |
| select |
| State_Manager.Wait_For_Change; |
| then abort |
| Dest := Source; |
| end select; |
| |
| -- there are two implementation methods for the |
| -- assignment statement: |
| -- 1. no temporary was used in the assignment statement |
| -- thus the entire |
| -- assignment statement is abort deferred. |
| -- 2. a temporary was used in the assignment statement so |
| -- there are two assignment operations. An abort may |
| -- occur between the assignment operations |
| -- Various optimizations are allowed by 7.6 that can affect |
| -- how many times Adjust and Finalize are called. |
| -- Depending upon the implementation, the state can be either |
| -- Finished_Adjust or Finished_Finalize. If it is any other |
| -- state then the abort took place at the wrong time. |
| |
| case State_Manager.Current is |
| when Finished_Adjust => |
| if Verbose then |
| Report.Comment ("assignment aborted after adjust"); |
| end if; |
| when Finished_Final => |
| if Verbose then |
| Report.Comment ("assignment aborted after finalize"); |
| end if; |
| when Start_Adjust => |
| Report.Failed ("assignment aborted in adjust"); |
| when Start_Final => |
| Report.Failed ("assignment aborted in finalize"); |
| when Start_Init => |
| Report.Failed ("assignment aborted in initialize"); |
| when Finished_Init => |
| Report.Failed ("assignment aborted after initialize"); |
| when Unknown => |
| Report.Failed ("assignment aborted in unknown state"); |
| end case; |
| |
| |
| if Dest.Id /= 3 then |
| if Verbose then |
| Report.Comment ("assignment not performed"); |
| end if; |
| end if; |
| end; |
| |
| |
| -- check dynamically allocated objects |
| State_Manager.Reset; |
| declare |
| type Pointer_Type is access Is_Controlled; |
| procedure Free is new Ada.Unchecked_Deallocation ( |
| Is_Controlled, Pointer_Type); |
| Ptr : Pointer_Type; |
| begin |
| -- make sure initialize is done when object is allocated |
| Ptr := new Is_Controlled; |
| Check_State (Finished_Init, "init when item allocated"); |
| -- now try aborting the finalize |
| State_Manager.Reset; |
| select |
| State_Manager.Wait_For_Change; |
| then abort |
| Free (Ptr); |
| end select; |
| Check_State (Finished_Final, "finalization in dealloc"); |
| end; |
| |
| Report.Result; |
| |
| end C980003; |