8.1.5 Exception support.

The co-dependency between the language itself (specifically attributes) and the library is also to be found when dealing with exceptions.

Library specification - package Ada.Exceptions.

The type Exception_Id above is vitally important as it is returned by the attribute 'Identity applied to an exception name.

This package has two important implications. Firstly by using the 'Identity attribute and the library subprogram Raise_Exception you can associate a message with the exception, providing diagnostic or context information. The example below shows how to associate a message with an exception and how to display the message in the exception handler.

with Ada.Exceptions; use Ada.Exceptions;
with Ada.Text_IO; use Ada.Text_IO;

procedure Exception_Test is

   My_Exception : exception;
begin

   Raise_Exception(My_Exception'Identity, "Whoops");

exception
   when An_Occurrence : My_Exception =>
      Put_Line("My_Exception raised, Message = " &
               Exception_Message(An_Occurrence));
end Exception_Test;

That part of the exception handler between the when and the => is now treated as a declaration with An_Occurrence an instance of the type Exception_Occurrence declared in the library package above. This means that any of the subprograms taking a parameter of type Exception_Occurrence can use the newly introduced object (note that the object is a constant and cannot be changed in any way).

This plays a big part in the second usage of this package - saving exceptions. For example consider a program where two tasks are running, the first is executing almost constantly querying some resource and placing data in a protected type to be read by the second task. If the first task receives an exception while processing the resource it needs to inform the reading task of an error, it could of course simply place an error record into the buffer, but it would not identify the actual exception so we can save the exception and raise it when the client reads the buffer.

..
   protected body Shared_Buffer is
      type Actual_Node is limited
         record
            Is_Data      : Boolean := True;
            Data         : Data_Type;
            An_Exception : Exception_Occurrence;
         end record;

      Actual_Buffer : array(1 .. 1000) of Actual_Node;
      First, Last : Natural;

      procedure Write_Exception(Actual : Exception_Occurrence) is
      begin
         Actual_Buffer(Last).Is_Data := False;
         Save_Occurrence(Actual_Buffer(Last).An_Exception,
                         Actual);
         ..
      end Write_Exception;

      function Read return Data_Type is
      begin
         if not Actual_Buffer(First).Is_Data then
            Reraise_Exception(Actual_Buffer(First).An_Exception);
         ..
      end Read;
   end Shared_Buffer;

   task body Resource_Handler is
   begin
      loop
         begin
            Buffer.Write_Data(..);
         exception
            when Actual : others =>
               Buffer.Write_Exception(Actual);
         end ;
      end loop;
   end Resource_Handler;
..

The incomplete example above shows how the buffer can store either data items or exceptions and can re-raise an exception to inform the client of the error indicated by the resource handler.


Previous PageContents PageNext Page

Copyright © 1996 Simon Johnston &
Addison Wesley Longman