880 likes | 1.41k Views
Introduction to Ada 95. Joyce L Tokar, PhD tokar@pyrrhusoft.com. Course Outline . History and Overview Large Scale View of Ada Conventional Features Packages and Overloading System Programming Features Object Oriented Features Real-Time Features Tools and Environments .
E N D
Introduction to Ada 95 Joyce L Tokar, PhD tokar@pyrrhusoft.com
Course Outline • History and Overview • Large Scale View of Ada • Conventional Features • Packages and Overloading • System Programming Features • Object Oriented Features • Real-Time Features • Tools and Environments
Afternoon Session • Look into the support for Systems programming, Real-Time programming, and Object-Oriented programming. • Look at the tools and environments available for developing Ada applications.
Ada 95 Highlights • Upward Consistent • Six new reserved words: • abstract, aliased, protected, requeue, tagged, until • 8-bit Character Type • Small efficiency improvements • Building on Ada 83 concepts • Private and derived types for data abstraction and OOP. • Subprogram and entries for user-defined and protected operations. • Packages for structuring the program library and distributed applications.
Ada 95 Highlights • Systems Programming Support • Child library units • Interfaces • Real-Time Programming Enhancements • Protected types for data-oriented synchronization • Requeue of an entry caller • Asynchronous transfer of control • Object-Oriented Features • Tagged type extension • User-defined type classes and dispatching operations • User-defined initialization, finalization, and assignment
Ada 95 Systems Programming • Hierarchical Libraries • Generics • Interfacing to other languages
Program Libraries • The Ada program library brings important benefits by extending the strong typing across the boundaries between separately compiled units. • The flat nature of the Ada 83 library gave problems of visibility control. It prevented two library packages from sharing a full view of a private type. Resulting packages became large and monolithic maintenance nightmares. • A more flexible and hierarchical structure was necessary.
Systems Programming Enhancements • Subsystem facilities. • Facilities to “hide” auxiliary units within subsystems. • Subsystem interfaces that involve private types. • Signification reduction in recompilation. • Support for interfacing to other systems.
Hierarchical Libraries • Library unit may have child library units. • Share private parts amongst children. • Allows disciplined type extension of private types. • Allows for incremental development. • Clients with only those units they need directly. • Clients are recompiled only when those units are changed. • Direct support for subsystem concept.
Hierarchical Libraries package Complex_Numbers is type Complex is private; function "+"(X,Y : Complex) return Complex; ... -- similar functions for "-", "*", and "/" function Cartesian_to_Complex (Real, Imag : Float) return Complex; function Real_Part(X : Complex) return Float; function Imag_Part(X : Complex) return Float; private ... end Complex_Numbers;
“with” clause • with clause -- used to give visibility to a library unit. • This allows you to access components of Complex_Numbers using dot notation (formally known as selected component notation). • The with clause gives visibility to anything found in the specification of the withed unit. with Complex_Numbers; procedure CALCULATE is My_Complex : Complex_Numbers.Complex; begin My_Complex := Complex_Numbers.Cartesian_to_Complex(3.2, -1.0); end CALCULATE;
“use” clause • use clause -- used to give direct visibility into a library unit. • Requires the corresponding withclause first. • This allows access to the components within the Complex_Numbers library unit without dot notation. with Complex_Numbers; use Complex_Numbers; procedure CALCULATE is My_Complex : Complex; begin My_Complex := Cartesian_to_Complex(3.2, -1.0); end CALCULATE;
Child Library package Complex_Numbers.Polar is function Polar2Complex(R, Theta : Float) return Complex; function "abs"(X : Complex) return Float; function ARG(X : Complex) return Float; end Complex_Numbers.Polar;
Hierarchical Libraries with Complex_Numbers.Polar; -- implies with Complex_Numbers; package Client1 is R : Float := 0.0; Angle : Float := 45.0; P1 : Complex_Numbers.Complex := Complex_Numbers.Polar.Polar2Complex(R, Angle); end Client1;
Hierarchical Libraries with Complex_Numbers.Polar; use Complex_Numbers; -- Child name Polar and components of the specification -- of Complex_Numbers are directly visible. package Client1 is R : Float := 0.0; Angle : Float := 45.0; P1 : Complex := Polar.Polar2Complex(R, Angle); end Client1;
Hierarchical Libraries with Complex_Numbers.Polar; use Complex_Numbers; -- Child name Polar and components of the specification of -- Complex_Numbers are directly visible. package Client1 is use Polar; -- Components of the child Polar are directly visible. R : Float := 0.0; Angle : Float := 45.0; P1 : Complex := Polar2Complex(R, Angle); end Client1;
Private Children • A private child is typically used to add additional functionality to the parent. • They prevent the parent from growing too large. • Private children can only be seen by the bodies of their ancestor. • Typically, they are withed by the body of their parent. • A private child is never visible outside of the tree rooted at the parent. • In essence, the first private child down a long chain hides anything below it from outside view.
Private Children private package Complex_Numbers.Hidden_Operations is --Types and procedures in this package can be used --in the body of Complex_Numbers. end Complex_Numbers.Hidden_Operations;
Visibility Rules • Declarations in the parent visible part are visible throughout specifications and bodies of children. • Declarations in the parent private part are visible in the private part and body of public children and throughout private children specifications and bodies; but not in public children specification parts. • Public children can be made visible anywhere with a with clause. • Private children can be made visible from the specifications or bodies of other private descendants of the parent, or from the parent body. • Child packages and nested packages may not have the same identifier as a name.
Friends don’t let friendsuse use • Leads to problems during maintenance. • Makes debugging difficult. • Pollutes the name space. use
Summary of Hierarchical Libraries • Child library units support hierarchical structuring of a large system into subsystems • Recompilation of clients is minimized by modularizing a large subsystem interface into visible child units. • Recompilation of the implementation of a subsystem is minimized by modularizing into private child units. • A package can be effectively extended by adding a new visible child, without disturbing existing clients.
Children of Generics • Generic packages can have children. • The child of a generic package must itself be a generic unit. • The child generic unit can only be instantiated in two ways: • Inside the generic body of its parent; • As a child of an instance of its parent. • A child of an instance must itself be an instance.
Children of Generics generic type Floating is digits <>; package Generic_Complex_Numbers is type Complex is private; function "+" (X, Y : Complex) return Complex; … private type Complex is record Real : Floating; Imag : Floating; end record; end Generic_Complex_Numbers;
Children of Generics generic package Generic_Complex_Numbers.Cartesian is function Construct (R, I : Floating) return Complex; function Real_Part (X : Complex) return Floating; function Imaginary_Part (X : Complex) return Floating; end Generic_Complex_Numbers.Cartesian;
Children of Generics with Generic_Complex_Numbers; with Generic_Complex_Numbers.Cartesian; procedure D_to_A is type My_Float is new Float digits 6; package My_Complex_Numbers is new Generic_Complex_Numbers( My_Float ); package My_Cartesian_Numbers is new My_Complex_Numbers.Cartesian; Y : My_Float := 0.0; X : My_Float := 34.3; C : My_Complex_Numbers.Complex := My_Cartesian_Numbers.Construct( X, Y );
Generics and HierarchicalLibraries • A library unit cannot be compiled until other library units mentioned in its with clause are entered into the library. • A subunit cannot be compiled until its parent body is entered into the library. • A body cannot be compiled until the specification of its parent is entered into the library. • A child cannot be compiled until the specification of its parent is entered into the library. • A package specification and body form a single declarative region.
Generics and Hierarchical Libraries • A library package can only have a body if it needs one to satisfy other language rules. • Do not attempt to redefine Standard. • Renaming is not text substitution. • A library unit could not be renamed as another library unit in Ada 83/87. • A subprogram body could not be provided by renaming in Ada 83/87.
Other Language Interfaces • Ability to reference (or call) Ada entities from other languages and to reference (or call) entities from Ada code. • Set of new pragmas: Export, Import, Convention • Export entities created by the Ada program to other programs. • Import entities created by other programs into the Ada program. • Convention specifies the calling conventions or data layouts. • Call-back/call-out via dispatching operations on tagged types. • Call-back via subprogram access • package Interfaces
Import Interface type Matrix is array (1..100, 1..100) of Integer; pragma Convention( ZZ_Fortran, Matrix ); -- Matrix is to be laid-out in conformance with the format that is used -- by ZZ_Fortran. Fortran_Matrix : Matrix; pragma Import( ZZ_Fortran, Fortran_Matrix, Link_Name => “Values” ); -- the object Fortran_Matrix is created by foreign code, where it is -- called “Values”; no storage will be allocated for its Ada declaration. function Multiply( A,B : Matrix ) return Matrix; pragma Import( ZZ_Fortran, Multiply, “_multi” ); -- the body of Multiply is provided by some routine name _multi with -- ZZ_Fortran calling convention; to be supplied externally.
Access Types • Pool-specific access types • General access types • Access parameters • Access discriminants • Access to subprograms • Storage pool management
Access Parameters procedure Main is type T is ...; type A is access all T; Ref : A; procedure P( Ptr : access T ) is begin ... Ref := A( Ptr ); -- dynamic check on conversion end P; X : aliased T; begin P( X’Access ); ... -- can now manipulate X via Ref end Main;
Access Parameters • The actual parameter corresponding to an access parameter can be: • An access to an aliased object such as X’Access; • Another access parameter with the same accessed type; • A value of a named access type again with the same accessed type; • An allocator. • An access parameter can be: • Used to provide access to the accessed object by dereferencing; • Passed as a parameter to another access parameter; • Converted to a named access type.
Access to Subprograms type Trig_Function is access function( F : Float ) return Float; S,C,T : Trig_Function; -- these variables can point to any function that has -- a float as a parameter and returns a float value. X, Theta : Float; … S := Sin'Access; C := Cos'Access; T := Tan'Access; Theta := Some_Degree; X := T.all(Theta); -- As with many uses with access types the .all is not usually -- required; it would be necessary if there were no parameters.
Call Backs type Button is private; type Action is access procedure(B : in out Button); procedure Set_Action(B : Button; A : Action); pragma Import(ANSI_C, Set_Action, ... ); -- some procedure in ANSI_C that expects a reference to -- a subprogram which will be called from within the foreign -- code when some event occurs. procedure My_Action(B : in out Button); . . . Set_Action(Some_Button, My_Action’Access); -- registers the Ada procedure My_Action for call back -- from foreign code.
package Interfaces • Defined in the required annex called Interface to Other Languages • Contains declarations of various machine integer types plus shift and rotate functions for modular types. • Includes a number of child packages: • Interfaces.C • Interfaces.C.Strings • Interfaces.C.Pointers • Interfaces.COBOL • Interfaces.Fortran
Objects are single values Scalar Composite Objects contain components Protected Coordinated access to shared data Tagged Inheritance and runtime polymorphism Access Objects point to other objects & subprograms Objects are abstract Private Objects are parallel processes Task Classes of Ada Types Ada Types
Improved Real-Time Capabilities • More efficient data communication and synchronization. • Building blocks to construct common real-time paradigms. • More control of task scheduling.
Protected Types • A synchronization mechanism which provides access to shared data without including an additional task. • A low-level, real-time building block that may be used to construct common real-time paradigms. • Low-level, light weight, data synchronization mechanism. • Encapsulation of shared data and access operations. • Similar to Conditional Critical Region with Signals.
Protected Operations • Protected functions provide read-only access to the protected type data components. • Protected procedures provide exclusive read-write access to the protected type data components. • Protected entries provide exclusive read-write access to the protected type data components with guarded access.
Simple Protected Type protected type Shared_Data is function Read return Data_Type; procedure Write(New_Data : in Data_Type); private Data : Data_Type; end Shared_Data; Spec protected body Shared_Data is function Read return Data_Type is begin return Data; end Read; procedure Write(New_Data : in Data_Type) is begin Data := New_Data; end Write; end Shared_Data; Body
Using Protected Types SD1 : Shared_Data; SD2 : Shared_Data; SDA : array( Index_Range ) of Shared_Data; … task body T1 is task body T2 is … … beginbegin … … D1 := SD1.Read; SD1.Write(D2); … … end T1; end T2;
Protected Object The Entry Barriers Protected EntriesTwo Levels of Protection • The entry barrier is used to indicate a change in the state of the protected object; every protected entry must specify an entry barrier. • All barriers are examined at the completion of a protected operation that may have changed the state of the protected object; e.g, at the end of a protected procedure or protected entry call. • Task's waiting for a protected entry barrier condition to become true are enqueued on the protected entry's queue.
Counting Semaphore Specification protected type Counting_Semaphore ( Initial_Count : Integer := 1 ) is entry Acquire; -- "P" Operation procedure Release; -- "V" Operation function Current_Count return Integer; private Count : Integer := Initial_Count; end Counting_Semaphore;
Counting Semaphore Body protected body Counting_Semaphore is entry Acquire when Count > 0 is -- Suspend until Count > 0, then decrement Count begin Count := Count - 1; end Acquire; procedure Release is begin Count := Count + 1; -- Increment Count end Release; function Current_Count return Integer is begin return Count; -- return the current value of Count end Current_Count; end Counting_Semaphore;
Counting Semaphore in Use Max_Users : constant := 10; -- Maximum Number of Users of Service User_Semaphore : Counting_Semaphore ( Max_Users ); procedure Use_Service( P : Param ) is begin User_Semaphore.Acquire; -- wait if there are too many Users begin -- critical region Perform_Service( P ); exception when others => -- Always release the semaphore for the next user. User_Semaphore.Release; raise; end; -- critical region User_Semaphore.Release; -- Release the semaphore for the next user. end Use_Service;
protected Buffer is entry Put( X : Item ); entry Get( Z : out Item ); private Full : Boolean := False; Y : Item; end Buffer; protected body Buffer is entry Put( X : Item ) when not Full is begin Y := X; Full := True; end; entry Get( Z : out Item ) when Full is begin Z := Y; Full := False; end; end Buffer; Buffer Manager
Buffer Manager in Use Buffer Producer Consumer Put(X) Get(X) task body Producer is X : Item; begin loop -- Produce X Buffer.Put( X ); end loop; end Producer; task body Consumer is Z : Item; begin loop Buffer.Get( Z ); -- Consume Z end loop; end Consumer;
Asynchronous Transfer of Control • Allows a sequence of statement to be interrupted and then abandoned after some event. • Used for mode change, time bounded computations, user-initiated interrupts, etc. • Triggering alternative can be either the completion of an entry call, or the expiration of a delay statement. select triggering_alternative;then abort abortable_part;end select;
Event Processing loop select Keyboard_Await_Cancel; Put_Line( “Canceled” ); then abort -- This code is abortable Put( “->” ); Get_Command( Command, Last ); Do_Command( Command( 1..Last ) ); end select; end loop; Timeout -- Cancel computations when a -- timeout occurs select delay 1.5; then abort Complex_Function(FIR_Range); end select; ATC in Use