1 / 21

Ada Constructs Revisited 21 Oct. 2002

Ada Constructs Revisited 21 Oct. 2002. Constructs to be Expanded. Generics Tasking Elaboration. Generics. Generic units are used to make Ada’s strong types less painful Possible to create general unit once, but use it for many different declared types

Download Presentation

Ada Constructs Revisited 21 Oct. 2002

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. AdaConstructsRevisited21 Oct. 2002

  2. Constructs to be Expanded • Generics • Tasking • Elaboration

  3. Generics • Generic units are used to make Ada’s strong types less painful • Possible to create general unit once, but use it for many different declared types • Has types, variables, subprograms, and packages as parameters • When each instance is made of a generic unit, it might be a separate copy, or it might share code

  4. Non-Generic Version package Complex_Numbers is type Complex is private; . . . function Construct (Real : Float; Imaginary : Float) return Complex; function “+” (X, Y: Complex) return Complex; . . . private type Complex is record Real_Part : Float; Imaginary_Part : Float; end record; end;

  5. Non-Generic Body package body Complex_Numbers is . . . function Construct (Real : Float; Imaginary : Float) return Complex is begin return Complex’(Real, Imaginary); end Construct; function “+” (X, Y: Complex) return Complex is begin return Complex’( (X.Real_Part + Y.Real_Part), (X.Imaginary_Part + Y.Imaginary_Part) ); end “+”; . . . end Complex_Numbers;

  6. Generic Example generic type My_Float is digits <>; package Generic_Complex_Numbers is type Complex is private; . . . function Construct (Real : My_Float; Imaginary : My_Float) return Complex; function “+” (X, Y: Complex) return Complex; . . . private type Complex is record Real_Part : My_Float; Imaginary_Part : My_Float; end record; end;

  7. Generic Body – Almost Identical to Non-Generic package body Generic_Complex_Numbers is . . . function Construct (Real : My_Float; Imaginary : My_Float) return Complex is begin return Complex’(Real, Imaginary); end Construct; function “+” (X, Y: Complex) return Complex is begin return Complex’( (X.Real_Part + Y.Real_Part), (X.Imaginary_Part + Y.Imaginary_Part) ); end “+”; . . . end Generic_Complex_Numbers;

  8. Instantiating a Generic with Generic_Complex_Numbers; procedure Test is type Small_Float_type is digits 6; type Large_Float_type is digits 14; package Small_Complex is new Generic_Complex_Numbers (Small_Float_type); use Small_Complex; package Large_Complex is new Generic_Complex_Numbers (Large_Float_type); use Large_Complex; Small_Real_Part : Small_Float_type := 1.234_567; Small_Imaginary_Part : Small_Float_type := 2.345_678; Large_Real_Part : Large_Float_type := 3.456_789_101_112; Large_Imaginary_Part : Large_Float_type := 4.567_891_011_121_3; Small_Complex_Number : Small_Complex.Complex := Construct (Small_Real_Part, Small_Imaginary_Part); Large_complex_Number : Large_Complex.Complex := Construct (Large_Real_part, Large_Imaginary_Part); begin Small_Complex_Number := Small_Complex_Number + Small_Complex_Number; Large_Complex_Number := Large_Complex_Number + Large_Complex_Number; end Test;

  9. Tasking • Multitasking (what UNIX people call Threads) is built in to the Ada language • Model is parallel activities • Easily implemented to use multiple processors • Implementation can use any scheduling mechanism • Time slicing, where each task (of the same priority) gets a bit of time, then the next task runs • One task runs until it hits a blocking point, then the next task (of the same priority or lower) runs • Priority can be used (if supported) to force the system to run tasks in a certain order (if running on a single processor system)

  10. The rendezvous • “two people meet, perform a transaction and then go on independently” • Between two tasks: one task calls an entry declared in another. Task Specification task T is entry E( … );end; Some other Task T.E( … ); Task Body accept E( … ) do --sequenceof statementsend E;

  11. Example: semaphore Simple mechanism to create critical sections: section of code that must be executed by only one task at a time task type Semaphore is entry P; -- Dijkstra’s terminology entry V; -- Passeren (lock) end Semaphore; -- Vrimajken (unlock) task body Semaphore is begin loop accept P; accept V; -- will not accept another P until a caller asks for V end loop; end Semaphore;

  12. Using a semaphore • A task that needs exclusive access to the critical section executes: Semaphore.P; … -- critical section code Semaphore.V; • If in the meantime another task calls Semaphore.P, it blocks, because the semaphore does not accept a call to P until after the next call to V: the other task is blocked until the current one releases by making an entry call to V. • Programming hazards: • someone else may call V : race condition • no one calls V: other callers are deadlocked • Starvation is possible if the queue is not a FIFO queue

  13. Timing and scheduling • Time slicing • Priorities • Real-Time Systems annex (Annex D) • Task can be held up of different reasons • Waiting for: • a partner in a rendezvous • dependent task to terminate • delay 3.0; Seconds: constant duration := 1.0;Minutes: constant Duration := 60.0;Hours: constant Duration := 3600.0; delay 2*Hours+40*Minutes;

  14. Example loop delay 5*Minutes; Action;end loop; Want cyclic execution. Any problems with this solution?

  15. Same, but different … declare use Calendar; Interval: constant Duration := 5*Minutes; Next_Time: Time := First_Time;begin loop delay until Next_Time; Action; Next_Time := Next_Time + Interval;end loop;end;

  16. “Protected Variable” • Protect a variable V from uncontrolled access. package Protected_Variable isprocedure Read(X: out Item);procedure Write(X: in Item);end; package body Protected_Variable is V: Item := initial value; procedure Read(X: out Item) is begin X := V;end; procedure Write(X: in Item) is begin V := X;end; end Protected_Variable; Any problems? type Item isrecordX_Coord: Float; Y_Coord: Float;end record;

  17. Protected Object Example package Variable is type My_Type is . . .; protected P_Variable is function Read return My_Type; -- Many callers procedure Write ( -- One caller X : in My_Type ); private V : My_Type := 0; end P_Variable; end Variable; • Any number of tasks may call protected functions at the same time • Protected functions can not write to protected objects • Not possible for a task to call Write while another calls Read (the second will block)

  18. Bounded buffer I J N: constant := 8;type Index is mod N;type Item_Array is array (Index) of Item; protected type Buffering isentry Put(X: in Item);entry Get(X: out Item);privateA: Item_Array; I,J: Index := 0; Count: Integer range 0..N := 0;end Buffering; protected body Buffering is entry Put(X: in Item) when Count < N is begin A(I) := X; I := I+1; Count := Count + 1;end Put; entry Get(X: out Item) when Count >0 is beginX := A(J); J := J + 1; Count := Count – 1;end Get; end Buffering; My_Buffer : Buffering;…My_Buffer.Put(X);

  19. Elaboration • Ada programs perform work before the first executable statement after the “begin” of the main procedure is run • “Elaboration” code is executed first • Gives data initial values (which might call functions) • Creates objects (if dynamic) • Runs package initialization code • To be completely precise, the whole program is one big elaboration • Package specifications are elaborated before their bodies • Package bodies are elaborated before any of their subprograms can be called • Package bodies can have task bodies, which start running after the package body has been elaborated • When all packages have been elaborated, the main procedure runs

  20. Elaboration Example with Ada.Text_IO; procedure Elab_Test is package Random_Pack is -- Elaboration of this is first type My_Type is digits 6 range 0.0 .. 1.0; function Random return My_Type; end Random_Pack; package body Random_Pack is -- Elaboration of this is second Seed : My_Type; function Random return My_Type is task My_Task; task body My_Task is X : My_Type := Random; begin Ada.Text_IO.Put ("Made it"); end My_Task; begin return Seed; -- For now, return a constant end Random; begin Seed := 0.5; -- Need this before Random can be called end Random_Pack; -- After last statement after "begin", My_Task can run use Random_Pack; Z : My_Type := Random; -- Executes the Random function begin null; end Elab_Test;

  21. Watch Out for Circular Dependencies package My_Pack is type My_type is range 1_000 .. 1_000_000; procedure Do_Something (Parameter : in out My_type); end My_Pack; package Other_Pack is type Other_type is range 0 .. 1_000; function Do_Something_Else return Other_type; end Other_Pack; with Other_Pack; pragma Elaborate (Other_Pack); package body My_Pack is X : Other_Pack.Other_type := Do_Something_Else; -- Needs Other_Pack body elab ... end My_Pack; with My_Pack; package body Other_Pack is X : My_Pack.My_type; ... end Other_Pack;

More Related