Re: Tasking problem (delay)



-- You can copy and paste to a file: 'test5.adb'
--
-- GNAT executable program follows after a few comments:
--

--
-- For another example try the
--
-- 'Dining Philosophers - Ada 95 edition'
--
-- which starts with the file 'diners.adb'
-- and includes a set of 5 extra packages.
--
-- The files should be in the example directory
-- that is include with GNAT. If not look on the
-- net.
--
--

--
-- As for Style. the LRM allows for style but it not require
-- by LRM. With that said you may have unprotected global
-- variables it is your choice! Plus it allow you to create
-- your own programming style.
--
--
-- Also useage of an accept statement to shutdown is shown to be
-- abnormal or premature RM 9.7.1 (24). While the terminate
-- statement is normal. But to shutdown a task which has
-- terminate statement within a loop, external task must use
-- the ABORT statement. Which is defined as valid RM 9.3 (18).
--


with Ada.Text_IO ;
use Ada.Text_IO ;

procedure Test5 is


-- ------------------------------- --
-- Declaration of Global Variables --
-- ------------------------------- --

Timeout_Constant : Duration ; -- Used as a constant once task
-- are active


-- -------------------- --
-- Declaration of Tasks --
-- -------------------- --

--
-- I remove startup task because since it is a set of code that
-- is normally execute once, which normally it does not need
-- it own task. It is better to insert the code either in a
-- master procedure or a master task which in your case, that
-- would be the 'Worker' task
--

task receiver is
entry Start ;
entry Shut_Down ; -- abnormal shutdown entry point
end receiver ;

task worker is
--
-- Inserting T for testing purposes only
--
entry Data ( T : in Boolean ) ;
end worker;


-- ---------------- --
-- Bodies for Tasks --
-- ---------------- --


task body receiver is

Z : Boolean := False ; -- only use for testing purposes in call

begin

-- Insert Receiver Initialization Code
--
-- Gives time for system to activate other tasks
-- and to execute initialization or startup code
--

Put_Line ( "Receiver: Initialization code" ) ;
delay 1.0 ; -- inserted for testing only

-- Main Receiver Task Code

loop
select
accept Start do
-- ... -- receive data

-- value insures watch dog will be executed
for index in 0..3 loop
Put_Line ( "Receiver: Data transfer to worker" ) ;
worker.Data ( Z ) ;

Put_Line ( "Receiver: Delay 1.0" ) ;
delay 1.0 ; -- inserted for testing only,
end loop ;
end start ;
or
--
-- From RM 9.7.1 (24) not acceptable termination routine
--
accept shut_down ;
Put_Line ( "Receiver: Abnormal ShutDown" ) ;
exit ;
or
--
-- Normal task shutdown routine
-- terminate is use by abort statement to stop code
--
terminate ;
end select ;
end loop ;
--
-- Code define here will never be execute if external abort
-- statement is use But if the Accept shut_down statement with a
-- exit statement is execute then this code will be executed
--
Put_Line ( "Receiver: Extra Abnormal ShutDown Code" ) ;
end receiver ;



task body worker is
--
-- Watch Dog Timeout variables
--
Timeout_Counter : Duration := 10.0 ;

Time_Slice : Duration := 0.1 ; -- smallest delay used in
-- this example


Q : Boolean ; -- used for testing


begin
loop
select
accept Data ( T : in Boolean ) do

--
-- Receive and process data
--
Put_Line ( "WORKER: Processing Data" ) ;
Q := T ;
--
-- reset timeout counter
--
Put_Line ( "WORKER: Reset Watch Dog counter" ) ;
Timeout_Counter := Timeout_Constant ;
end Data ;

or
-- -- -- -- -- -- --
-- Watch Dog Routine --
-- -- -- -- -- -- --

--
-- wait for timed delay
--
delay Time_Slice ;
Put_Line ( "WORKER: Has Time Slice" ) ;
Timeout_Counter := Timeout_Counter - 0.1 ;
--
-- Check for time_out
--
if ( Timeout_Counter < 0.1 ) then
exit ;
end if ;
end select ;
end loop ;
--
-- Without the abort statement the receive task will
-- hang the process.
--
Put_Line ( "WORKER: shutdown Receiver Task" ) ;
--
-- receiver.shut_down ; -- abnormal shutdown
--
abort receiver ; -- Normal Task Shutdown

Put_Line ( "WORKER: shutdown self: (Worker task)" ) ;
end worker ;


begin
--
-- Insert startup code HERE!
--
Put_Line ( "TEST5: Startup code" ) ;
Timeout_Constant := 2.0 ;
--
-- Start receiver task
--
Put_Line ( "TEST5: Activate Receiver Task " ) ;
Receiver.Start ;


Put_Line ( "TEST5: Waiting for Watch Dog Timeout" ) ;
--
-- Wait for the death of the receiver task
--
while Receiver'callable loop
delay 1.5 ;
end loop ;


Put_Line ( "TEST5: Delay before shutdown" ) ;
Delay 1.0 ; -- Give system some time before killing this task
Put_Line ( "TEST5: ShutDown" ) ;

end test5 ;











In <1187197490.377548.41000@xxxxxxxxxxxxxxxxxxxxxxxxxxxx>, Gerd <GerdM.O@xxxxxxxxxxx> writes:
Hi all,

I have a problem with some code. Maybe I misunderstood the LRM. Can
someone explain and maybe show a solution?

First I have to say, I work with GNAT on Windows, but what I try is to
simulate the behavior of an embedded processor (which is currently
programmed in C).

I have three tasks (much reduced from real world task), one for
startup, one for receiving data and one for processing it:

WD_Delay: Duaration := 1000.0; -- so do not trigger on start

task startup is
end startup;

task receiver is
end receiver;

task worker is
entry Data(...);
end worker;

task body startup is
begin
...
WD_Delay := 1.0;
...
end startup;

task body receiver is
begin
loop
... -- receive data
worker.Data (...);
end loop;
end receiver;

task body worker is
begin
loop
select
accept Data (...)
or
delay WD_Timeout;
trigger_WD;
end select;
end loop;
end worker;


So what I expected was, that after the init-task set the new delay,
the worker would trigger the watchdog in short intervalls. But it
seems, that the delay still waits for the initial delay time.
Whats wrong?

Thanks,
Gerd


.



Relevant Pages