Possible language changes

Jim Rogers jimmaureenrogers at att.net
Fri Mar 4 01:56:53 GMT 2005


----- Original Message ----- 
From: "Douglas C. Schmidt" <schmidt at dre.vanderbilt.edu>
>   /**
>    * Send @a signum to @a thread_id.  Not supported on platforms
>    * that do not have advanced signal support, such as Win32.
>    * Can throw various exceptions on failure (TBD).
>    */
>   void signal (thread_t thread_id,
>                int signum);

Your signal handling example above requires advanced signal support.
Do you have a more generalized solution to signal handling in a threaded
application? For instance, what would you provide for Win32?  It is 
certainly a platform which cannot currently be ignored.

Ada treats all signal handling as a concurrent processing situation.
Interrupts are handled through the creation of a protected object
designated as an interrupt handler. An interrupt (signal) is associated
with a parameterless procedure in that protected object.
A task is then created that calls an entry on the same protected object 
and suspends until an interrupt is received by the protected object.

The following simple example demonstrates how Ada can capture
interrupt.

with Ada.Interrupts.Names;
use Ada.Interrupts.Names;
package Handlers is
   pragma Unreserve_All_Interrupts;
   -- Declare a protected object to handle SIGINT
   protected Handler is
      procedure Counter; 
      entry Wait_For_Interrupt; 
      pragma Attach_Handler(Counter,Sigint);
   private
      Count : Natural := 0;
   end Handler;
   -- Declare a task to wait for signal to be handled
   task Int_Handler is
      entry Stop; 
   end Int_Handler;
end Handlers;

with Ada.Text_Io;
use Ada.Text_Io;
package body Handlers is
   -- Define the signal handler protected object
   protected body Handler is
      procedure Counter is 
      begin
         Count := Count + 1;
      end Counter;
      entry Wait_For_Interrupt when Count > 0 is 
      begin
         Count := Count - 1;
      end Wait_For_Interrupt;
   end Handler;
   -- Define the task that will respond to signals
   task body Int_Handler is
      Num_Interrupts : Natural := 0; 
   begin
       loop
         select
            Handler.Wait_For_Interrupt;
            Num_Interrupts := Num_Interrupts + 1;
            Put_Line("handled interrupt #" &
            Natural'Image(Num_Interrupts));
        or
           delay 0.001;
           select
               accept Stop; 
               exit;
             or
               delay 0.0;
            end select;
         end select;
      end loop;
   end Int_Handler;
end Handlers;

-----------------------------------------------------------------------
-- Interrupt Demonstration
-- This program declares a dependency upon the signal handler defined
-- in the Handlers package. This will cause the handler protected object
-- and the int_handler task to be started.
-----------------------------------------------------------------------
with Ada.Text_Io;
with Handlers;
procedure Sig_Handler is 
begin
   for Num in 1..20 loop
      Ada.Text_Io.Put_Line("Iteration" & Integer'Image(Num));
      delay 1.0;
   end loop;
   -- shut down the int_handler task
   Handlers.Int_Handler.Stop;
end Sig_Handler;

The procedure Sig_Handler in this program is equivalent to a "main" in
C++. Sig_Handler simply prints out a line once per second indicating 
the number of times it has gone through its "for" loop. Sig_Handler calls
the Stop entry for the Int_Handler task defined in the Handlers package
when the loop completes.

Every time the program receives a SIGINT the protected procedure
Handlers.Counter is called, incrementing the Count data member of
the Handlers protected object. The Int_Handler task suspends on its
call to the entry Handlers.Wait_For_Interrupt until the Count data
member contains a value > 0.

The example above is actually a bit more sophisticated than that.
It calls the entry and suspends for no more than 0.001 seconds.
If no interrupt is received within the 0.001 second time period the
program checks to see if the Stop entry for the task has been called.
If the Stop entry has been called the task exits its loop and terminates.
If an interrupt has been received within the specified 0.001 seconds the
task handles the interrupt then loops back to call Wait_For_Interrupt
again.

As soon as the procedure Handlers.Counter completes, the boundary
condition for Handlers.Wait_For_Interrupt is re-evaluated and Counter
is decremented. 

This approach allows the system to respond to interrupts even when 
they are received faster than the handler can handle an individual 
interrupt.

Jim Rogers







More information about the cpp-threads mailing list